第七部分:第二节 - 在 Node.js 中连接和操作 MySQL:厨房与仓库的沟通渠道

发布于:2025-05-24 ⋅ 阅读:(19) ⋅ 点赞:(0)

要让 Node.js 后端应用(厨房)与 MySQL 数据库(仓库)进行交互,我们需要一个数据库驱动程序 (Database Driver)。驱动程序就像厨房与仓库之间的通信员,它知道如何用仓库管理员(MySQL Server)能理解的语言(SQL)发送指令,并把仓库的回应(查询结果)带回来。

Node.js 有多个可用的 MySQL 驱动,比较流行且推荐的是 mysql2,它支持 Promise API,更适合现代异步编程风格。

安装 mysql2:

在你的 Node.js 项目目录中(非 NestJS 项目,先以纯 Node.js 脚本为例):

npm install mysql2
# 或者 yarn add mysql2

建立数据库连接:

在操作数据库之前,首先需要建立一个连接。连接信息包括数据库地址(host)、端口、用户名、密码、数据库名等。

// connect_db.js
const mysql = require('mysql2');

// 创建数据库连接
const connection = mysql.createConnection({
  host: 'localhost',  // 数据库地址
  user: 'your_mysql_username', // 你的 MySQL 用户名
  password: 'your_mysql_password', // 你的 MySQL 密码
  database: 'my_webapp_db' // 要连接的数据库名
});

// 连接到数据库
connection.connect(err => {
  if (err) {
    console.error('数据库连接失败:', err.stack);
    return;
  }
  console.log('成功连接到数据库,连接 ID:', connection.threadId);

  // 在这里执行数据库操作...

  // 操作完成后关闭连接 (在实际应用中通常使用连接池)
  // connection.end();
});

// 注意:在实际应用中,不应将敏感信息直接写在代码中,应使用配置文件或环境变量。

执行 SQL 查询:

mysql2 支持回调和 Promise 两种方式执行查询。推荐使用 Promise 方式,因为它与 async/await 配合更优雅。

Promise 方式:

// query_db.js
const mysql = require('mysql2/promise'); // 导入 Promise 版本的驱动

async function runQueries() {
  let connection;
  try {
    // 建立连接
    connection = await mysql.createConnection({
      host: 'localhost',
      user: 'your_mysql_username',
      password: 'your_mysql_password',
      database: 'my_webapp_db'
    });
    console.log('成功连接到数据库');

    // 执行 SELECT 查询
    const [rows, fields] = await connection.execute('SELECT * FROM users');
    console.log('查询结果:', rows); // rows 是一个包含查询结果的数组

    // 执行带参数的查询 (使用占位符 ?)
    const userId = 1;
    const [userRows] = await connection.execute('SELECT * FROM users WHERE id = ?', [userId]);
    console.log(`查询用户 ID ${userId}:`, userRows[0]); // 获取第一行结果

    // 执行 INSERT 查询
    const newUser = { username: 'charlie', email: 'charlie@example.com' };
    const [insertResult] = await connection.execute('INSERT INTO users (username, email) VALUES (?, ?)', [newUser.username, newUser.email]);
    console.log('插入结果:', insertResult);
    console.log('新用户 ID:', insertResult.insertId); // 获取新插入记录的 ID

  } catch (err) {
    console.error('数据库操作出错:', err);
  } finally {
    // 确保连接关闭
    if (connection) {
      await connection.end();
      console.log('数据库连接已关闭');
    }
  }
}

runQueries();

// 运行这个文件: node query_db.js

connection.execute() 方法返回一个 Promise, resolved 后得到一个数组,第一个元素是查询结果(对于 SELECT 是行数据,对于 INSERT/UPDATE/DELETE 是操作影响的信息),第二个元素是字段信息(通常不常用)。

连接池 (Connection Pool):

反复创建和关闭数据库连接是有开销的。在高并发场景下,为每个请求都创建新连接会导致性能问题。连接池是一组预先创建好的数据库连接,当需要执行数据库操作时,从池中获取一个连接;操作完成后,将连接归还给池,而不是关闭。这就像仓库门口有一个服务台,提前准备好了一些推车(连接),需要搬东西时直接领用推车,用完归还,而不是每次都去制造一个新推车。

在 Node.js 应用中,尤其是在 Express 或 NestJS 应用中,强烈推荐使用连接池。

// pool_db.js
const mysql = require('mysql2/promise');

// 创建连接池
const pool = mysql.createPool({
  host: 'localhost',
  user: 'your_mysql_username',
  password: 'your_mysql_password',
  database: 'my_webapp_db',
  waitForConnections: true, // 如果连接都忙,等待连接可用
  connectionLimit: 10,     // 池中最大连接数
  queueLimit: 0          // 连接队列最大长度,0 表示无限制
});

async function getUserById(userId) {
  let connection;
  try {
    // 从连接池获取一个连接
    connection = await pool.getConnection();
    console.log(`连接 ID ${connection.threadId} 从连接池获取`);

    const [rows] = await connection.execute('SELECT * FROM users WHERE id = ?', [userId]);

    return rows[0]; // 返回第一个用户
  } catch (err) {
    console.error('获取用户出错:', err);
    throw err; // 抛出错误以便上层处理
  } finally {
    // 确保连接归还给连接池
    if (connection) {
      connection.release();
      console.log(`连接 ID ${connection.threadId} 归还给连接池`);
    }
  }
}

// 调用函数获取用户
async function main() {
    const user = await getUserById(2);
    console.log('查找到的用户:', user);

    // 当应用关闭时,关闭连接池 (在 Express/NestJS 应用退出时执行)
    // await pool.end();
    // console.log('连接池已关闭');
}

main();

// 运行这个文件: node pool_db.js

小结: 使用数据库驱动程序(如 mysql2)是 Node.js 连接和操作 MySQL 的方式。Promise API 结合 async/await 使得异步数据库操作更易读。连接池是管理数据库连接、提高应用性能的关键,尤其在处理并发请求时。

练习:

  1. 在你之前的 Node.js 项目(非 Express/NestJS)中安装 mysql2
  2. 使用 Promise 方式编写一个脚本,连接到你的 my_bookstore_db 数据库。
  3. 执行一个 SELECT * FROM books 查询,并将所有书籍信息打印到控制台。
  4. 编写一个函数,接收书籍 ID 和新的出版年份作为参数,使用 UPDATE 语句更新指定书籍的出版年份。在脚本中调用该函数并测试。
  5. (进阶)修改你的脚本,使用连接池来执行查询。

网站公告

今日签到

点亮在社区的每一天
去签到