Node.js Koa2 连接 MySQL 实战:从基础查询到 Sequelize ORM

作者:后端茶话时间:2026-10-25 15:30:00浏览:505

本文详解 Node.js 中 Koa2 连接 MySQL 的多种实现方式。涵盖 mysql2 基础用法、JSON 聚合函数处理复杂查询、预处理语句提升性能及连接池管理。同时介绍基于 Promise 的异步操作,并深入讲解如何使用 Sequelize ORM 进行对象关系映射,包括数据库配置、连接测试及单表、多表关联操作。

在数据库查询场景中,通常需要将返回的结果转换为对象或数组格式,以便在业务逻辑中更便捷地处理数据。

在实际项目开发中,某些特定的查询结果往往需要封装到对象结构中,以便后续的业务逻辑处理。

MySQL 提供了 JSON_OBJECT 函数,其语法要求括号内以 key-value 的形式定义字段映射关系。

SELECT products.id as id, products.title as title, products.price as price, products.score as score,
	JSON_OBJECT('id', brand.id, 'name', brand.name, 'rank', brand.phoneRank, 'website', brand.website) as brand
FROM products LEFT JOIN brand ON products.brand_id = brand.id;

在数据库查询场景中,通常需要将返回的结果转换为对象或数组格式,以便在业务逻辑中更便捷地处理数据。

在处理多对多关联关系时,查询目标通常是一个包含多个对象的数组。

  • 例如,获取某学生的多门课程信息时,数据应组织为数组结构。
  • 该数组内部存储的是代表各课程信息的独立对象。
  • 为实现这一需求,需结合使用 JSON_ARRAYAGG 与 JSON_OBJECT 函数。

在数据库查询场景中,通常需要将返回的结果转换为对象或数组格式,以便在业务逻辑中更便捷地处理数据。

SELECT stu.id, stu.name, stu.age,
	JSON_ARRAYAGG(JSON_OBJECT('id', cs.id, 'name', cs.name)) as courses
FROM students stu
LEFT JOIN students_select_courses ssc ON stu.id = ssc.student_id
LEFT JOIN courses cs ON ssc.course_id = cs.id
GROUP BY stu.id;

接下来介绍 mysql2 库的具体应用。

首先通过 npm 安装 mysql2 依赖。

npm install mysql2

以下是 mysql2 的基础使用示例。

const mysql = require('mysql2');

// 1.创建数据库连接
const connection = mysql.createConnection({
  host: 'localhost',
  port: 3306,
  database: 'coderhub',
  user: 'root',
  password: 'Coderwhy888.'
});

// 2.执行SQL语句
const statement = `
  SELECT * FROM products WHERE price > 6000;
`
connection.query(statement, (err, results, fields) => {
  console.log(results);
});

若需在获取数据后终止服务,可在回调函数中调用连接结束方法。

connection.end()

以下是完整的查询代码示例。

connection.query(statement, (err, results, fields) => {
  console.log(results);
  connection.end();
});

预处理语句(Prepared Statement)是提升数据库交互效率的关键机制。

其核心原理是将 SQL 语句模板发送至 MySQL 服务器,由服务器进行解析、优化并编译存储,但不立即执行。后续执行时,只需向 ? 提供实际参数即可触发执行;即使多次执行,也仅编译一次,从而显著提升性能。

需注意,再次执行该语句时,MySQL 会从 LRU(最近最少使用)缓存中直接获取已编译的语句对象,从而省略编译时间,进一步优化性能。

// 2.执行SQL语句: 使用 ?来对参数进行占位
const statement = `
  SELECT * FROM products WHERE price > ? AND score > ?;
`
connection.execute(statement, [6000, 7], (err, results) => {
  console.log(results);
});

连接池(Connection Pools)用于高效管理数据库连接资源。

前文示例仅创建单一连接,若面临高并发请求,该连接可能处于占用状态。此时,是否每次请求都需新建连接?

  • 实际上,mysql2 提供了连接池功能以解决此问题。
  • 连接池可根据需求自动创建连接,且这些连接不会被销毁,而是保留在池中供后续请求复用。
  • 在初始化连接池时,可设置 LIMIT 参数以限制最大连接数。

以下是判断数据库连接是否成功的示例代码。

const mysql = require('mysql2');

// 1.创建连接池
const connections = mysql.createPool({
  host: 'localhost',
  port: 3306,
  database: 'coderhub',
  user: 'root',
  password: 'Coderwhy888.',
  connectionLimit: 10
});

connections.getConnection((err, conn) => {
  conn.connect((err) => {
    if(err){
      console.log('连接失败:',err)
    } else {
      console.log('数据库连接成功~')
    }
  })
})

以下是使用数据库的简化操作流程。

const mysql = require('mysql2');

// 1.创建连接池
const connections = mysql.createPool({
  host: 'localhost',
  port: 3306,
  database: 'coderhub',
  user: 'root',
  password: 'Coderwhy888.',
  connectionLimit: 10
});

// 2.使用连接池
const statement = `
  SELECT * FROM products WHERE price > ? AND score > ?;
`
connections.execute(statement, [6000, 7], (err, results) => {
  console.log(results);
});

介绍基于 Promise 的异步数据库操作方式。

const mysql = require('mysql2');

// 1.创建连接池
const connections = mysql.createPool({
  host: 'localhost',
  port: 3306,
  database: 'coderhub',
  user: 'root',
  password: 'Coderwhy888.',
  connectionLimit: 10
});

// 2.使用连接池
const statement = `
  SELECT * FROM products WHERE price > ? AND score > ?;
`
connections.promise().execute(statement, [6000, 7]).then(([results,fields]) => {
  console.log(results);
}).catch(err => {
  console.log(err);
});

Sequelize 是 Node.js 生态中广泛使用的 ORM 框架。

对象关系映射(ORM)是一种程序设计范式。

  • 从效果上看,它允许开发者在编程语言中通过虚拟对象来操作数据库。

在 Node.js 开发中,通常选用 Sequelize 作为 ORM 工具。

  • Sequelize 支持 Postgres、MySQL、MariaDB、SQLite 及 Microsoft SQL Server 等多种数据库,是基于 Node.js 的 ORM 库。
  • 该框架支持丰富的功能特性。

若希望将 Sequelize 与 MySQL 配合使用,需预先安装两个关键组件。

  • mysql2:Sequelize 在操作 MySQL 时依赖此驱动。
  • sequelize:用于实现对象到数据库表的映射逻辑。
npm install sequelize mysql2

以下是 Sequelize 的具体使用步骤。

首先演示如何连接数据库。

第一步:实例化 Sequelize 对象,并指定数据库名称、用户名、密码、数据库类型及主机地址等配置参数。

第二步:执行测试以验证连接是否成功建立。

const { Sequelize } = require('sequelize');

const sequelize = new Sequelize('coderhub', 'root', 'Coderwhy888.', {
  host: 'localhost',
  dialect: 'mysql'//连接的数据库类型:mysql,mongoose
});

sequelize.authenticate().then(() => {
  console.log("连接数据库成功~");
}).catch(err => {
  console.log("连接数据库失败~", err);
});

接下来介绍 Sequelize 的单表数据操作。

const { Sequelize, DataTypes, Model, Op } = require('sequelize');

const sequelize = new Sequelize("coderhub", 'root', 'Coderwhy888.', {
  host: 'localhost',
  dialect: 'mysql'
})

//1.首先我们需要将数据库中的一张表映射成一个class类
class Product extends Model {}
Product.init({
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,//主键
    autoIncrement: true//自动增长
  },
  title: {
    type: DataTypes.STRING,
    allowNotNull: false//是否可以为空
  },
  price: DataTypes.DOUBLE,
  score: DataTypes.DOUBLE
}, {//与数据库的表进行映射的配置
  tableName: 'products',
  createdAt: false,
  updatedAt: false,
  sequelize
});

//存放操作数据库的代码
async function queryProducts() {
  //1.查询数据库中product表中所有的内容
  const result1 = await Product.findAll({
    where: {//在这里配置条件
      price: {
        [Op.gte]: 5000//意思是价格大于等于5000
        //gte:大于等于,gt:大于,lt:小于,lte:小于等于
      }
    }
  });
  console.log(result1);

  // 2.插入数据
  const result2 = await Product.create({
    title: "三星Nova",
    price: 8888,
    score: 5.5
  });
  console.log(result2);

  // 3.更新数据
  const result3 = await Product.update({
    price: 3688
  }, {
    where: {
      id: 1
    }
  });
  console.log(result3);
}

queryProducts();//执行这个函数可以实现对数据库的操作

随后讲解 Sequelize 的一对多关联操作。

const { Sequelize, DataTypes, Model, Op } = require('sequelize');

const sequelize = new Sequelize("coderhub", 'root', 'Coderwhy888.', {
  host: 'localhost',
  dialect: 'mysql'
});

//数据库的第一个表: 主表
class Brand extends Model {};
Brand.init({
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  name: {
    type: DataTypes.STRING,
    allowNotNull: false
  },
  website: DataTypes.STRING,
  phoneRank: DataTypes.INTEGER
}, {
  tableName: 'brand',
  createdAt: false,
  updatedAt: false,
  sequelize
});

//数据库的第二个表:附表
class Product extends Model {}
Product.init({
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  title: {
    type: DataTypes.STRING,
    allowNotNull: false
  },
  price: DataTypes.DOUBLE,
  score: DataTypes.DOUBLE,
  brandId: {
    field: 'brand_id',
    type: DataTypes.INTEGER,
    references: {//这张表使用了Brand的id作为外键
      model: Brand,//product这张表使用了Brand这个表,所以product必须放在下面
      key: 'id'
    }
  }
}, {
  tableName: 'products',
  createdAt: false,
  updatedAt: false,
  sequelize
});

// 将两张表联系在一起
Product.belongsTo(Brand, {
  foreignKey: 'brandId'//外键
});

async function queryProducts() {
  const result = await Product.findAll({
    include: { //这里是联合查询:意思是包含别的表的信息
      model: Brand
    }
  });
  console.log(result);
}

queryProducts();

最后说明 Sequelize 的多对多关联操作。

const { Sequelize, DataTypes, Model, Op } = require('sequelize');

const sequelize = new Sequelize("coderhub", 'root', 'Coderwhy888.', {
  host: 'localhost',
  dialect: 'mysql'
});

// Student表
class Student extends Model {}
Student.init({
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  name: {
    type: DataTypes.STRING,
    allowNotNull: false
  },
  age: DataTypes.INTEGER
}, {
  tableName: 'students',
  createdAt: false,
  updatedAt: false,
  sequelize
});

// Course表
class Course extends Model {}
Course.init({
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  name: {
    type: DataTypes.STRING,
    allowNotNull: false
  },
  price: DataTypes.DOUBLE
}, {
  tableName: 'courses',
  createdAt: false,
  updatedAt: false,
  sequelize
});

// StudentCourse表:关系表
class StudentCourse extends Model {}
StudentCourse.init({
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  studentId: {//与Student表建立关系
    type: DataTypes.INTEGER,
    references: {
      model: Student,
      key: 'id'
    },
    field: 'student_id'
  },
  courseId: {//与Course表建立关系
    type: DataTypes.INTEGER,
    references: {
      model: Course,
      key: 'id'
    },
    field: 'course_id'
  }
}, {
  tableName: 'students_select_courses',
  createdAt: false,
  updatedAt: false,
  sequelize
});

// 多对多关系的联系:Student StudentCourse Course
Student.belongsToMany(Course, {
  through: StudentCourse,
  foreignKey: 'studentId',//这里是Student与StudentCourse,所以外键是studentId
  otherKey: 'courseId'//StudentCourse与Course,所以外键是courseId
});

//与上面类似
Course.belongsToMany(Student, {
  through: StudentCourse,
  foreignKey: 'courseId',
  otherKey: 'studentId'
});

async function queryProducts() {
  const result = await Student.findAll({
    include: {//所有学生的选课情况
      model: Course
    }
  });
  console.log(result);
}

queryProducts();

至此,关于 Node.js 中 Koa2 连接 MySQL 的实现示例介绍完毕。如需了解更多相关 Koa2 连接 MySQL 的内容,请搜索本站往期文章或继续阅读后续相关文章,感谢大家的支持!

作者最新文章