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

从零学习Node.js框架Koa 【四】Koa 与数据库(MySQL)连接,实现CRUD操作

系列文章目录

从零学习Node.js框架Koa 【一】 Koa 初探从环境搭建到第一个应用程序
从零学习Node.js框架Koa 【二】Koa 核心机制解析:中间件与 Context 的深度理解
从零学习Node.js框架Koa 【三】Koa路由与静态资源管理:处理请求与响应
从零学习Node.js框架Koa 【四】Koa 与数据库(MySQL)连接,实现CRUD操作
从零学习Node.js框架Koa 【五】Koa鉴权全解析:JWT+Redis构建安全认证系统


文章目录

  • 系列文章目录
  • 前言
  • 一、MySQL 环境准备
    • 1、MySQL安装
    • 2、 数据库管理工具
  • 二、Koa连接MySQL
    • 1、安装依赖:
    • 2、数据库连接配置
    • 3、在入口文件(app.js)使用
    • 4、连接池配置常用的属性说明
  • 三、Koa操作MySQL
    • 1、操作API execute()和query()讲解
      • (1) execute
      • (2) query
      • (3)execute和query区别
    • 2、 基本增删改查(CRUD)操作
      • (1)插入数据(INSERT)
      • (2)更新数据(UPDATE)
      • (3) 删除数据(DELETE)
    • (4) 查询数据(SELECT)
      • 1、查询所有数据
      • 2、条件查询数据
      • 3、模糊查询
      • 4、分页查询
      • 4、排序查询
      • 5、计数
        • (1)查询所有记录总数
        • (2)获取条件查询记录总数
  • 四、总结


前言

        Web服务端开发离不开数据的存储、数据库的操作。MySQL 作为最常用的关系型数据库,是实际项目开发的首选。而在Koa框架中也有非常适合的中间件帮助我们快速集成和操作MySQL 。本篇文章将继续介绍如何在 Koa 中集成 MySQL,完成基础的 CRUD 操作。


一、MySQL 环境准备

1、MySQL安装

以window系统为例:
打开官方网站,

在这里插入图片描述

选择 “Windows (x86, 64-bit), MSI Installer“ 安装包,点击《Download》,跳转到下载页面:

在这里插入图片描述

点击”No thanks, just start my download.“开始下载。

下载完成双击安装包,按向导操作

在这里插入图片描述
在这里插入图片描述

选择“Custom”自定义安装方式

在这里插入图片描述

默认安装在C盘,点击Browse按钮可选择安装目录,记住这里选择的安装目录后面需要使用。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
安装完成点击“Finish” 进入配置设置

在这里插入图片描述

设置数据存储位置,有需要修改其他目录

在这里插入图片描述

在这里插入图片描述

接下来设置root用户密码,2个输入框密码一致,务必记住密码后续需要使用

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

点击《Execute》,等待配置完成
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
到此MySQL 程序安装和基础配置就完成了,接下来设置环境变量。

window+i组合按键打开Window设置,搜索“高级系统设置”-打开系统属性设置窗口

在这里插入图片描述

点击右下角“环境变量“
在这里插入图片描述
在系统变量中找到path并选中,点击“编辑”
在这里插入图片描述
在编辑环境变量窗口中新建变量,路径输入mysql安装目录\bin,确定关闭
在这里插入图片描述

校验是否安装成功:

window+R,输入cmd,打开cmd窗口输入:

mysql -u root -p

进行MySQL连接测试

在这里插入图片描述
输入密码——回车,出现如下图所示表示连接成功

在这里插入图片描述
至此,MySQL安装和所有配置工作就都完成了。

2、 数据库管理工具

操作数据库既可以通过命令行也可以选择可视化MySQL管理工具,对于不熟悉命令行的新手,推荐使用可视化管理工具,常用的可视化管理工具有Navicat、Workbench、DBeaver等,根据具体需求和个人偏好选择合适的工具。

以Navicat为例简单说明使用步骤:

(1)点击左上角“连接”按钮——选择MySQL创建连接

在这里插入图片描述

(2)输入连接名(自定义),主机默认localhost,端口默认3306,用户名默认root,输入密码——确认,创建成功在左侧列表新增一个连接(MySQL)显示

在这里插入图片描述

(3)右击“MySQL连接“选择“打开链接”

在这里插入图片描述

打开成功,左侧列表显示默认创建好4个数据库

在这里插入图片描述

(4)右击MySQL新建数据库,输入数据库名、字符串选择“utf8mb4”,排序规则选择
“utf8mb4_0900_ai_ci”——确定

在这里插入图片描述

(5)打开新建的数据库(project),右击表选择新建表,在右边窗口添加字段,添加完保存——输入表名——确定 表创建完成。

在这里插入图片描述
在这里插入图片描述
Navicat的使用简单介绍到这,如需更详细的使用教程可以自行查找网上其他文章。


二、Koa连接MySQL

接下来讲解本文重点——Koa连接操作数据库。 在 Node.js 生态中,mysql2 库因其卓越的性能和完整的 Promise 支持成为操作 MySQL驱动首选。

1、安装依赖:

npm install mysql2

2、数据库连接配置

创建config/db.js文件配置数据库连接:

const mysql = require("mysql2/promise");
// 创建连接池
const pool = mysql.createPool({host: "localhost",//数据库服务器地址,默认localhostport: 3306,// 默认端口user: "root", //用户名,默认rootpassword: "123456",//密码database: "project", //数据库名称// 连接池配置waitForConnections: true,// 没有连接时等待connectionLimit: 10, // 连接池最大连接数queueLimit: 0,    // 等待队列无限制(0表示不限制)
});// 测试数据库连接
async function testConnection() {try {const connection = await pool.getConnection();console.log("数据库连接成功");connection.release();// 释放连接回池} catch (e) {console.log(e, "数据库连接失败");}
}//执行测试
testConnection()module.exports = pool;

说明:上述代码创建了一个数据库连接池实例和测试连接是否成功方法,默认执行了连接测试方法,并导出连接池实例。

为什么用连接池?因为 “每次请求创建一个数据库连接” 的成本很高(TCP 握手、认证等步骤耗时),连接池会提前创建一批连接,请求来时直接复用,用完放回池里,大幅提升性能。

3、在入口文件(app.js)使用

//app.js
const Koa = require("koa");
const app = new Koa();
require("./config/db.js");//连接数据库const port = 3001; //端口号
app.listen(port, () => {console.log(`服务器运行在 http://localhost:${port}`);
});

运行项目:

在这里插入图片描述
控制台上显示“数据库连接成功”,证明连接配置成功。

4、连接池配置常用的属性说明

属性类别属性名默认值说明使用建议
基础连接属性hostlocalhost数据库服务器地址,本地连接默认使用localhost,远程连接需填写目标服务器IP远程连接时需确保服务器开放MySQL默认端口(3306)或自定义端口
基础连接属性user数据库登录用户名推荐创建专用业务用户并分配最小权限,禁止直接使用root用户
基础连接属性password登录用户对应的密码生产环境需通过环境变量(如dotenv库)管理,禁止硬编码在代码中
基础连接属性database要连接的目标数据库名称需提前创建数据库,并为登录用户授权该数据库的操作权限
基础连接属性port3306MySQL服务监听的端口号若修改过MySQL默认端口,需与服务器配置保持一致
连接池核心属性connectionLimit10连接池允许的最大并发连接数小型项目建议5-10,中大型项目20-50,需结合服务器性能动态调整
连接池核心属性waitForConnectionstrue无空闲连接时,新请求是否进入队列等待生产环境建议设为true,避免请求直接失败影响用户体验
连接池核心属性queueLimit0连接等待队列的最大长度,0表示无限制默认保持0即可,高并发场景可设100-200,防止队列过长导致内存溢出
连接池核心属性idleTimeout60000ms(1分钟)空闲连接的超时时间,超时后自动关闭释放服务器资源短连接业务可设30000ms(30秒),长连接业务可设5-10分钟
辅助优化属性enableKeepAlivetrue是否启用TCP长连接机制,保持连接活跃建议开启,减少频繁建立和断开TCP连接的性能开销
辅助优化属性charsetutf8mb4数据库连接使用的字符集必须与数据库、表的字符集一致,避免中文乱码

三、Koa操作MySQL

mysql2 连接池实例上有execute、query2个方法可以执行sql语句进行数据库CRUD。两者使用方法相似。

1、操作API execute()和query()讲解

(1) execute

语法:

const [results, fields]=await pool.execute(sqlStr, [...values])

其中pool为连接池实例, 第一个入参为sql原生语句字符串,值用“?”占位符代替,第二个入参为数组,数组每个元素对应占位符“?”的值。

返回值:一个二维数组[results, fields]

  • results :执行结果数据,内容随操作类型变化,查询类操作(SELECT、COUNT、SUM 等),results 是个数组,包含查询到的行数据。. 写操作(INSERT、UPDATE、DELETE),results 是一个对象,包含操作影响的行数、插入 ID 等元数据。

  • fields :字段元信息(仅查询类操作有意义),包含字段名、数据类型、表名等描述性信息(一般业务代码中用得少,调试时可查看)。

示例:

//从users表中查找id=13的用户数据const [rows] = await pool.execute(`SELECT * FROM users  WHERE id = ? `,[13])console.log(rows) //[{name:'张三',sex:1,age:20}]

(2) query

语法:

const [results, fields]=await pool.query(sqlStr, [...values])

和execute用法一样

示例

//往users表中插入一条数据:字段name值为张三,字段email值为'123456@@qq.comconst [result]= await pool.query(`INSERT INTO users (name, email) VALUES (?, ?)`,['张三','123456@@qq.com'])console.log(results.insertId) //20:新增记录的自增 ID

除了和execute相同的使用方法外,query还支持sql动拼接参数法。

上述的示例可以改为:

 const name='张三';const email='123456@@qq.com';const result= await pool.query(`INSERT INTO users (name, email) VALUES (${name}, ${email})`,

query 2中方法区别:?是参数化查询的占位符,主要用于防止 SQL 注入攻击,同时让代码更安全。实际开发中推荐使用占位符法。

(3)execute和query区别

尽管两者在代码使用上相似,但是内部执行机制有着本质上的区别:

  • execute:原生支持预处理语句,会先将 SQL 模板(含占位符?)发送给 MySQL 编译,后续仅传递参数执行,重复执行相同结构 SQL 时(如批量新增数据),仅编译一次 SQL,后续复用执行计划,性能更优。

  • query:无预处理机制,直接将完整 SQL 字符串发送给 MySQL 执行,每次执行都需编译 SQL,重复执行相同 SQL 时性能较差,只适合简单静态 SQL(无参数拼接,如SELECT * FROM users),或一次性执行的 SQL。

综上所述,推荐全部使用execute进行数据库操作。


2、 基本增删改查(CRUD)操作

(1)插入数据(INSERT)

新增一条用户数据:

原生SQL语句:

//向users表插入一条新数据(姓名张三(name=张三)、性别男(sex=1)、年龄25(age=25)、邮箱为12345@qq.com(email=12345@qq.com))
INSERT INTO users (name, sex,age,email) VALUES ('张三', 1,25,'12345@qq.com')

koa实现:

router.post("/api/users", async (ctx) => {let { name, sex, age, email} = ctx.request.body;//执行sqllet [result]=await pool.execute("INSERT INTO users (name, sex,age,email) VALUES (?, ?,?,?)", [name, sex, age, email]);ctx.body = {code: 200,message: "创建用户成功",data:result.insertId //返回新用户id};
});

(2)更新数据(UPDATE)

修改表中用户数据:

原生SQL语句:

//修改表uses中id=13的用户姓名为张三(name='张三')、邮箱为12345@qq.com(email=12345@qq.com)
UPDATE users SET name = '张三', email = '12345@qq.com' WHERE id = 13

koa实现:

router.put("/api/users/:id", async (ctx) => {let { id } = ctx.params;let {name,email}=ctx.request.body;//执行sqllet [result]=await pool.execute("UPDATE users SET name = ?, email = ? WHERE id = ?",[name, email, id]);ctx.body = {code: 200,message: "修改用户成功",data: result.affectedRows,//受影响的行数 (1)};
});

(3) 删除数据(DELETE)

删除一条用户数据:

原生SQL语句:

//删除表users中id=13的用户数据
DELETE FROM users WHERE id = 13

koa实现:

   router.delete("/api/users/:id", async (ctx) => {let { id } = ctx.params;//执行sqllet [result]=await pool.execute("DELETE FROM users WHERE id = ?", [id]);ctx.body = {code: 200,message: "修删除用户成功",data: result.affectedRows,//受影响的行数 (1)};
});

(4) 查询数据(SELECT)

已知当前数据库含有3条用户数据

在这里插入图片描述

1、查询所有数据

原生SQL语句:

//查询表users 所有行数据
SELECT * FROM users

koa实现:

router.get("/api/users", async (ctx) => {//执行sqllet [result] = await pool.execute("SELECT * FROM users");ctx.body = {code: 200,message: "查询用户列表成功",data: result,};
});

执行结果:

在这里插入图片描述

2、条件查询数据

单条件查询:查找年龄大于25的用户

原生SQL语句:

//查询表users中年龄大于25的用户
SELECT * FROM users WHERE age > 25

koa实现:

router.get("/api/users", async (ctx) => {const {age}=ctx.query;//执行sqllet [result] = await pool.execute("SELECT * FROM users WHERE age > ?",[Number(age)]);ctx.body = {code: 200,message: "查询用户列表成功",data: result,};
});

执行结果:
在这里插入图片描述

多条件查询:查找年龄大于25并且是女性用户

原生SQL语句:

//查询表uses中年龄大于25且为女性的用户
SELECT * FROM users WHERE age > 25 AND sex = 2

koa实现:

router.get("/", async (ctx) => {const {age,sex}=ctx.query;//执行sqllet [result] = await pool.execute("SELECT * FROM users WHERE age > ? AND sex = ?",[Number(age),Number(sex)]);ctx.body = {code: 200,message: "查询用户列表成功",data: result,};
});

执行结果:
在这里插入图片描述

3、模糊查询

支持姓名或邮箱模糊搜索实现:

原生SQL语句:

//查询表users中姓名带“张”或邮箱带“58”用户
SELECT * FROM users WHERE name LIKE '%张%' OR email LIKE '%58%'

koa实现:

router.get("/", async (ctx) => {const {name,email}=ctx.query;//执行sqllet [result] = await pool.execute("SELECT * FROM users WHERE name LIKE ? OR email LIKE ?",[`%${name}%`,`%${email}%`]);ctx.body = {code: 200,message: "查询用户列表成功",data: result,};
});

执行测试:

查询张姓用户
在这里插入图片描述

邮箱关键词模糊搜索

在这里插入图片描述

说明:模糊查询通过 LIKE 搭配通配符实现,常用通配符:

  • ( % ):匹配任意长度的字符串(包括 0 个字符),例如 ‘李%’ 匹配 “李” 开头的字符串(“李白”“李世民” 等),“%白“匹配“白”为后缀的字符串(“王自白”,"明白"等),“%李%“匹配含有“李”关键字字符串不管在什么位置;
  • ( _ ):匹配单个字符,例如 ‘李_’ 匹配 “李” 开头且长度为 2 的字符串(“李白”“李四” 等,不匹配 “李世民”)。

4、分页查询

原生SQL语句:

//查询表users中第二条至第三条数据(每页2条,跳过前1条,从第2条开始取)
SELECT * FROM users LIMIT 2 OFFSET 1;

koa实现:

router.get("/", async (ctx) => {//执行sqllet [result] = await pool.execute("SELECT * FROM users LIMIT ? OFFSET ?",[BigInt(2),BigInt(1)]);ctx.body = {code: 200,message: "查询用户列表成功",data: result,};
});

执行结果:
在这里插入图片描述

ps:注意分页参数必须是BigInt类型不然执行会报错

4、排序查询

原生SQL语句:

//查询用户表所有记录并按年龄降序排列
SELECT * FROM users ORDER BY age DESC

Koa实现:

router.get("/", async (ctx) => {//执行sqllet [result] = await pool.execute("SELECT * FROM users ORDER BY age DESC");ctx.body = {code: 200,message: "查询用户列表成功",data: result,};
});

执行结果:
在这里插入图片描述
说明:降序DESC,升序ASC,多字段排序“,”连接

 const [result] = await pool.execute('SELECT * FROM users ORDER BY age ASC, email DESC, name ASC');

5、计数

(1)查询所有记录总数

原生SQL语句:

//查询用户表所有记录总数
SELECT COUNT(*) as total FROM users

Koa实现:

router.get("/", async (ctx) => {//执行sqllet [result] = await pool.execute("SELECT COUNT(*) as total FROM users");ctx.body = {code: 200,message: "计数成功",data: {total:result[0].total},};
});

在这里插入图片描述

(2)获取条件查询记录总数

原生SQL语句:

//查询用户表年龄为30的用户数量
SELECT COUNT(*) as total FROM users WHERE age = 30

Koa实现:

router.get("/", async (ctx) => {//执行sqllet [result] = await pool.execute("SELECT COUNT(*) as total FROM users WHERE age = ?",[30]);ctx.body = {code: 200,message: "计数成功",data: {total:result[0].total},};
});

在这里插入图片描述

注意:返回解构值result为数组,获取总数为result[0].total


四、总结

通过本文的详细讲解,我们完成了从MySQL环境搭建到Koa框架集成数据库的完整流程。我们不仅掌握了MySQL的安装配置和可视化工具的使用,更重要的是深入学习了如何在Koa应用中通过mysql2库高效地操作数据库。在下一篇文章中,我们将继续学习如何实现Koa鉴权功能。

http://www.dtcms.com/a/592881.html

相关文章:

  • Zotero在代理模式下无法同步问题
  • LeetCode(python)——438.找到字符串中所有字母异位词
  • 解决添加asp.net网站报错请添加 MIME 映射
  • 浙江省工程建设管理协会网站常州小程序开发公司
  • ASP vs ASP.NET vs ASP.NET Core:三代微软 Web 技术核心区别解析
  • 【项目设计】基于正倒排索引的Boost搜索引擎
  • 建网站需要几程序员关键词网站优化平台
  • 深圳网站建设方案书做sns网站需要什么
  • C语言常见推理题
  • leetcode 3542. 将所有元素变为 0 的最少操作次数 中等
  • 一文掌握,sward安装与配置
  • Supabase 开源 BaaS 平台的技术内核与实践指南
  • YOLOv5+DeepSORT目标检测
  • 通过Prometheus对GPU集群进行监控以及搭建(小型集群)
  • 【datawhale】Agentic AI学习笔记
  • 江苏国龙翔建设公司网站找工作网站建设
  • 网站建设及在线界面设计
  • Aloha浏览器 7.10.1 |私人浏览器,极速上网,资源嗅探
  • 多Agent协同-详解
  • Spring Boot 数据库操作实战:MyBatis 让 CRUD 像 “查奶茶库存” 一样简单
  • 电脑五笔打字入门口诀:3天学会五笔打字拆字
  • 自动驾驶中的B样条轨迹及B样条<->贝塞尔转换实现避障
  • 南阳市做网站网站开发是什么专业百度
  • 做外包的网站有哪些问题最好玩的网站
  • 阿尔及尔至广州直飞航线成功首航
  • 太原网站建设找山西云起时北京做网站优化的公司
  • 价值优先,敏捷致胜:超越“数据治理优先”的AI实施新范式
  • 2025年下半年软考高级系统架构师题目和答案
  • 基于多组学谱的疾病亚型分型与样本分类
  • 怎么做免费网站被收录营销推广的目标