在项目中操作数据库的步骤
1.1 安装操作MySQL数据库的第三方模块( mysql )
1.2 连接mysql 模块到 MySQL 数据库
1.3 通过 mysql 模块执行 SQL 语句
1. 安装 mysql 模块
mysql 模块是托管在npm 上的第三方模块 提供了在node.js项目中连接个操作MySQL数据库的能力,要在项目中使用mysql 需要先进行安装
npm install mysql
2.配置mysql 模块 连接数据库
在node.js中使用mysql模块 要先进行必要的配置
// 1.导入mysql模块
const mysql = require('mysql')
// 2.建立与MySQL数据库的连接
const db = mysql.createPool({
host: '127.0.0.1', //数据库的ip地址
user: 'root', //登录数据库的账号
password: 'admin123', //登录数据库的密码
database:'my_db_01' //指定要操作那个数据库
})
测试mysql模块是否可以正常使用(select 1 仅测试)
db.query("select 1", (err, res) => {
// 判断是否有err 有err则表示执行错误
if (err) return console.log(err.message);
console.log(res);//打印出 {'1':1} 表示可以正常使用 mysql 模块
});
结果:
3. 通过mysql执行SQL语句
db.query("select * from users", (err, res) => {
if (err) return console.log("mysql模块工作期间报错了", err.message);
console.log("成功执行了sql语句", res);
});
结果:
项目中可创建一个js文件 用于引入和配置mysql
使用:
postman测试接口
5. SQL语句
5.1执行select语句
// 查询数据库
db.query(`select * from users where id=${id}`, (err, result) => {
//向客户端响应数据库中对应参数的数据
res.send(result);
});
5.2 插入数据 insert into || insert into set
写法1:适用于字段少的时候,值可用?占位符,在调用db.query时传入参数即可(多个参数使用数组形式,单个参数时不需要使用数组形式)
语法格式:
insert into 表名 (字段名1,字段名2) values (值1,值2)
示例:
let user = { username: "hello", password: "123456" };
let sqlstr = "insert into users (username,password) values (?,?)"; //?为占位符 后续传参使用
db.query(sqlstr, [user.username, user.password], (err, result) => {
if (err) return console.log(err.message);
if (result.affectedRow === 1) {
console.log("添加成功");
}
});
写法2:简便写法 使用set ?代替整个对象
注意:参数对象的属性需要与表的字段一一对应
语法格式:
insert into 表名 set ?
示例:
// 简便写法 使用set ?占位符 在调用db.query的时候将参数对象传入 (注意:参数对象的属性与表的字段一一对应)
let sqlstr2 = "insert into users set ?";
db.query(sqlstr2, user, (err, result) => {
if (err) return consoloe.log(err.message);
if (result.affectedRows === 1) {
res.send("添加成功");
}
});
5.3 update语句更新数据
语法1:
语法格式:适用于字段少的情况下
update 表名 set 字段名1=?,字段名2=? where 字段名3=?
//?为占位符 后续调用db.query时需要传入实际的值
示例:
router.post("/user/update", (req, res) => {
let user = req.body;
let sqlstr = "update users set username=?,password=? where id=?";
db.query(sqlstr, [user.username, user.password, user.id], (err, result) => {
if (err) return consoloe.log(err.message);
if (result.affectedRows === 1) {
res.send("修改成功");
}
});
});
语法2:简便语法
语法格式:
update 表名 set ? where 字段名=?
示例:
// 简便写法
let user = req.body;
let sqlstr2 = "update user set ? where id=?"
db.query(sqlstr2, [user, 3], (err, result) => {
if (err) return consoloe.log(err.message);
if (result.affectedRows === 1) {
res.send("修改成功");
}
})
5.4 delete 语法删除数据
语法格式:
delete from 表名 where 字段名=?
示例:
router.post("/user/delete", (req, res) => {
let user = req.body;
let sqlstr = "delete from users where id=?";
db.query(sqlstr, user.id, (err, result) => {
if (err) return consoloe.log(err.message);
if (result.affectedRows === 1) {
res.send("删除成功");
}
});
});
注意:delete会直接删除数据库中的数据 ,如需要做模拟删除,可添加个字段用于判断是否被删除,后续删除时执行update语句更新该字段的值即可(标记删除)
优化res.send
在app.js引入路由先使用中间件
// 封装res.cc函数
app.use((req, res, next) => {
// status 默默人值为500 err的值可能是错误对象 也可能是字符串
res.cc = function (err, status = 500) {
res.send({
status,
message: err instanceof Error ? err.message : err,
});
};
next();
});
调用时直接使用res.cc即可
步骤:
1.安装 joi 包 为表单中携带的每个数据项 定义校验规则
npm install joi
2.@escook/express-joi 中间件,来实现自动对表单数据进行验证的功能
npm i @escook/express-joi
3.新建schema/user.js
const joi = require("joi");
/**
* string() 值必须是字符串
* alphanum() 值只能是包含 a-zA-Z0-9 的字符串
* min(length) 最小长度
* max(length) 最大长度
* required() 值是必填项,不能为 undefined
* pattern(正则表达式) 值必须符合正则表达式的规则
*/
// 用户名的验证规则
const username = joi.string.alphanum().min(1).max(10).required();
const password = joi
.string()
.pattern(/^[\S]{6,12}$/)
.required();
//定义验证注册和登录表单数据的规则对象
//向外暴露
exports.reg_login_schema = {
body: {
username,
password,
},
};
4.在router/user.js中导入使用
4.1.导入验证表单数据的中间件
4.2.导入校验数据规则 在路由url和回调函数之前使用中间件
// 1. 导入验证表单数据的中间件
const expressJoi = require("@escook/express-joi");
// 2.导入校验数据规则 在路由url和回调函数之前使用中间件
const { reg_login_schema } = require("../schema/user");
效果:
校验成功时会流转到处理函数,校验失败会流转到错误级别的中间件
在 app.js 的全局错误级别中间件中,捕获验证失败的错误,并把验证失败的结果响应给客户 端:
// 导入校验数据的包
const joi = require("joi");
//捕获err错误
app.use((err, req, res, next) => {
// 这个需要根据⾃自⼰己的业务逻辑来处理理
if (err.name === "UnauthorizedError") {
// jwt 解析token
return res.send({ status: 401, message: "token失效" });
}
// joi 校验表单失败
if (err instanceof joi.ValidationError) {
return res.send({ status: 410, message: "参数格式错误:" + err.message });
}
res.send({
status: 500,
message: "未知错误:" + err.message,
});
});
结果:
mysql和mysql2模块的区别:
mysql 和 mysql2 都是 Node.js 中常用的操作 MySQL 数据库的模块,
mysql:是 Node.js 中比较早期的 MySQL 操作模块,该模块底层使用的是回调函数(callback)来实现异步操作。在处理大量并发请求时,由于回调函数的嵌套会导致代码难以维护、阅读和调试,因此在性能和可维护性上都有一定的劣势。此外, mysql 模块在连接池等方面的表现也较为一般。
mysql2:是 mysql 模块的替代品,该模块使用 Promise 和回调函数(callback)两种方式来实现异步操作,因此在性能和可维护性上都具有优势。此外,mysql2 模块还新增了支持多语句查询、预处理语句等功能,提供了更丰富的 API,使用起来更方便。
因此,在实际开发中,建议使用 mysql2 模块来操作 MySQL 数据库,它相对于 mysql 模块更加稳定、灵活、易用。
mysql示例:
bd.js文件中 导出的是db
// 1.导入mysql模块
const mysql = require("mysql");
// 2.建立与MySQL数据库的连接
const db = mysql.createPool({
host: "127.0.0.1", //数据库的ip地址
user: "root", //登录数据库的账号
password: "admin123", //登录数据库的密码
database: "my_db_01", //指定要操作那个数据库
});
module.exports = db
使用:使用callbak的方式
let id = req.body.id; //拿到参数id
// 查询数据库
db.query(
`select id,username,nickname,email,user_pic from ev_users where id=${id}`,
(err, result) => {
//向客户端响应数据库中对应参数的数据
// res.send(result);
if (result && result.length > 0) {
res.send({
status: 200,
msg: "success",
data: {
username: result,
},
});
} else {
res.send({
status: 500,
msg: "暂无该id的用户",
});
}
}
);
mysql2示例:
bd.js文件中导出的是bd.promis()
// 1.导入mysql2模块
const mysql = require("mysql2");
// 2.建立与MySQL数据库的连接
const db = mysql.createPool({
host: "127.0.0.1", //数据库的ip地址
user: "root", //登录数据库的账号
password: "admin123", //登录数据库的密码
database: "my_db_01", //指定要操作那个数据库
});
module.exports = db.promise();
使用:async await 形式+try{}cath(){}捕获错误
async function getUser(req,res){
try {
let sqlstr = "select * from ev_users";
const [rows] = await db.query(sqlstr);
res.send({
status: 200,
data: rows,
});
} catch (err) {
res.send({
status: 500,
message: "执行sql错误" + err.message,
});
}
}