当前位置: 首页 > news >正文

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

要让 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. (进阶)修改你的脚本,使用连接池来执行查询。

相关文章:

  • Postgresql 数据库体系架构
  • 从逆流监测到智慧用电:ADL200N-CT系列单相导轨表赋能家庭绿色能源
  • 储能电站:风光储一体化能源中心数字孪生
  • TiDB迁移实战:解决“Region is unavailable”报错与隐式类型转换引发的索引失效
  • PHP序列化数据格式详解
  • 多模态大语言模型arxiv论文略读(九十)
  • 【Python 基础与实战】从基础语法到项目应用的全流程解析
  • 编程技能:字符串函数10,strchr
  • php 根据另一个数组中 create_time 的时间顺序,对原始数组进行排序。
  • 计算机操作系统(十二)详细讲解调计算机操作系统调度算法与多处理机调度
  • 使用 Elasticsearch 和 Red Hat OpenShift AI 提升工作流程效率
  • 什么是VR场景?VR与3D漫游到底有什么区别
  • CustomSVG,一键生成SVG,文字秒变矢量图(WIN/MAC)
  • 阿里开源 CosyVoice2:打造 TTS 文本转语音实战应用
  • Springboot通过SSE实现实时消息返回
  • [原创](计算机数学)(The Probability Lifesaver)(P14): 推导计算 In(1-u) 约等于 -u
  • 得力DE-620K针式打印机打印速度不能调节维修一例
  • C++ std::find() 函数全解析
  • Spyglass:CDC官方Hands-on Training(三)
  • 服务器数据迁移终极指南:网站、数据库、邮件无缝迁移策略与工具实战 (2025)
  • wordpress 文章分类/seo排名推广工具
  • 杭州有哪些做网站的公司好/深圳百度关键
  • 网站备案快吗/深圳推广公司哪家最好
  • 杭州企业seo网站优化/seo网页优化公司
  • 网站使用cookies/简述网站推广的方式
  • 政府网站内容建设/微信拓客的最新方法