ORM框架
OMR框架全程是Object Relational Mapping 对象-关系-映射。ORM框架就是将关系型数据库映射成面向对象模型,方便我们以操作对象的方式操作数据库。
ORM框架特点
- ORM框架的内部逻辑会实现sql防注入,对数据库操作只需要调用框架提供对应api即可,不需要担心原生sql问题。
- 可以提升开发效率,不需要写繁琐重复的sql语句。
- 调试sql会比较麻烦,但是很多框架都支持写原生sql。
- 复杂的sql语句,很难通过框架语法写出来,故可以用原生sql。
node主流的ORM框架
node的优秀ORM框架有很多,在这只列举主流的三种
TypeORM:支持 Active Record (活动记录)和 Data Mapper(数据映射) 模式;支持多种数据库;对 TS 的高度支持、简洁、支持装饰器语法;官网:https://typeorm.bootcss.com/。
Prisma:官方文档维护活跃、文档教程清晰;支持数据库较少;是对TypeScript支持最好的ORM;官网:https://prisma.yoga。
Sequelize:基于 promise 的 Node.js 的 ORM;支持多种数据库;具有强大的事务支持,关联关系,预读和延迟加载等功能;官网:https://www.sequelize.com.cn。
Sequelize基本介绍
Sequelize是单纯使用js开发;基于 promise 的 Node.js 的 ORM,目前支持 Mysql等多种数据库;具有强大的事务支持。其官方网站为:https://www.sequelize.cn/core-concepts/getting-started。
首先我们需要安装Sequelize
yarn add sequelize@6.24.0
如何再安装mysql数据库安装驱动程序
yarn add mysql2@2.3.3
配置数据库连接
在config\sequelize.js里面编写
const {Sequelize} = require('sequelize')
const sequelize = new Sequelize('database', 'username', 'password', {
host: 'localhost',
dialect: 'mysql',
port:''
})
database // 数据库名字
username // 用户名
password // 密码
host // 数据库运行的服务器ip地址
dialect // 数据库类型
port //端口号

将测试连接的这段代码加入到里面,再使用node config/sequelize.js启动项目,发现出现以下问题使用await但是没有添加异步导致出错,所有在外层添加async,改变后代码如下
(async function () {
try {
await sequelize.authenticate();
console.log('数据库链接成功');
} catch (error) {
console.error('数据库链接失败:', error);
}
})()
定义数据表模型同步和初试操作
创建数据库表:通过Sequelize框架创建数据库的表,此方法创建字段比可视化工具中慢,而且不清晰。
const { Sequelize, DataTypes } = require("sequelize");
const sequelize = require("../config/sequelize");
const User = sequelize.define(
"User",
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
username: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
tableName: "user",
timestamps: false,
}
);
(async () => {
await User.sync({ alter: true });
console.log("成功同步");
})();
module.exports = User;
模型同步
User.sync()
- 如果表不存在,则创建该表,否则,不执行任何操作
User.sync({ force: true })
- 将创建表,如果表已经存在,则将其首先删除
User.sync({ alter: true })
- 这将检查数据库中表的数据,然后在表中进行必要的更改以使其与模型匹配
模型简单插入操作
const express = require("express");
const app = express();
const cors = require("cors");
const User = require("./models/user");
app.use(cors());
app.get("/user", async(req, res) => {
await User.create({
username: "李四",
});
res.send("创建成功");
});
app.listen(8081, () => {
console.log("server is running at http://127.0.0.1:8081");
});
提高模型同步的开发效率
当我们数据库表中的字段如果非常多,有十几个二十几个字段的时候,如果一一创建模型,是不是过于繁琐和困难,这时候我们就想到了是否有这样的一个工具,可以根据我们的数据库表自动创建我们所需要的模型?这时候就要用到了SequelizeAuto。
官网地址:https://github.com/sequelize/sequelize-auto
安装方法:
yarn add sequelize-auto
运行命令:
node ./node_modules/sequelize-auto/bin/sequelize-auto -o "./models" -d test -h 127.0.0.1 -u root -p 3306 -x 123456 -e mysql
在package.json中编写以下代码,简化运行命令
"scripts": {
"models": "sequelize-auto -e mysql -h 127.0.0.1 -p 3306 -u root -x 123456"
}
然后使用这个命令
yarn models -d test --cm p
--cm p // 帕斯卡命名法(将所有单词首字母大写连接)
改变app.js里面的文件
const express = require("express");
const app = express();
const cors = require("cors");
const modules = require("./models/init-models.js");
const sequelize = require("./config/sequelize.js");
app.use(cors());
app.get("/user", async(req, res) => {
await modules(sequelize).User.create({
username: "老王",
});
res.send("创建成功");
});
app.listen(8081, () => {
console.log("server is running at http://127.0.0.1:8081");
});
请求该接口:http://127.0.0.1:8081/user,然后查看数据库观察是否添加数据成功。
Promise异步实现数据库增和查操作
const { Sequelize } = require("sequelize");
const initModules = require("../models/init-models.js");
const sequelize = new Sequelize("test", "root", "123456", {
host: "127.0.0.1",
dialect: "mysql",
port: 3306,
});
(async function () {
try {
await sequelize.authenticate();
console.log("数据库链接成功");
} catch (error) {
console.error("数据库链接失败:", error);
}
})();
const modules = initModules(sequelize);
module.exports = {sequelize, ...modules}
const express = require("express");
const app = express();
const cors = require("cors");
const {User} = require("./config/sequelize.js");
app.use(cors());
app.get("/user", async(req, res) => {
await User.create({
username: "老王",
});
res.send("创建成功");
});
app.listen(8081, () => {
console.log("server is running at http://127.0.0.1:8081");
});
通过Sequelize插入数据的操作(增)
app.get("/user", async(req, res) => {
await User.create({
username: "老王",
});
res.send("创建成功");
});
User.create()插入
Sequelize查询数据的操作(查)
app.get("/find", async(req, res) => {
await User.findAll({
where:{
username: "王",
age: 20
}
});
res.send("创建成功");
});
通过定义变量放回给前端的数据

通过控制台打印的数据
Executing (default): SELECT `id`, `username` FROM `user` AS `User` WHERE `User`.`username` = '王';
[
User {
dataValues: { id: 13, username: '王' },
_previousDataValues: { id: 13, username: '王' },
uniqno: 1,
_changed: Set(0) {},
_options: {
isNewRecord: false,
_schema: null,
_schemaDelimiter: '',
raw: true,
attributes: [Array]
},
isNewRecord: false
}
]
在where的同一级添加一个raw:true即可将控制台里面的数据打印为数组的格式
[ { id: 13, username: '王' } ]
也可以使用操作符形式,但是比较麻烦一般不使用
// Op操作符
const { Op } = require("sequelize");
DB.Account.findAll({
where: {
username: {
[Op.eq]: '老王'
}
}
});
Promise异步实现数据库改和删操作
Sequelize更新数据的操作(改)
王改为王老板
app.get("/update", async(req, res) => {
await User.update({
username:"王老板"
},{
where:{
username: "王",
}
}),
res.send("创建成功");
});
Sequelize删除数据的操作(删)
app.get("/del", async(req, res) => {
await User.destroy({
where:{
username: "王",
}
});
res.send("删除成功");
});
Promise一对一和一对多关系表关联和查询
一对一模型
// app.js
const express = require('express');
const app = express();
const cors = require('cors');
const { Desk, Student } = require('./config/sequelize.js')
app.use(cors());
app.get('/desk', async (req, res) => {
const resData = await Desk.findAll({
include: [{ model: Student, as: 'studentDetail' }]
})
res.send(resData)
});
app.listen(8081, () => {
console.log('服务启动在:http://127.0.0.1:8081')
})
一对多模型
// app.js
const express = require('express');
const app = express();
const cors = require('cors');
const { Class, Student } = require('./config/sequelize.js')
const { Op } = require('sequelize')
app.use(cors());
// 查学生表
app.get('/student_class', async (req, res) => {
const resData = await Student.findAll({
include: [{ model: Class, as: 'classDetail' }]
})
res.send(dbRes)
});
// 查班级表
app.get('/class', async (req, res) => {
const resData = await Class.findAll({
include: [{ model: Student, as: 'studentList' }]
})
res.send(resData)
});
app.listen(8081, () => {
console.log('服务启动在:http://127.0.0.1:8081')
})
Sequelize的Mysql事务
事务:有多个对数据库的操作sql语句,要么多个操作都成功,要么有一个失败就一起回滚
事务的四大特性ACID
Atomicity(原子性):
一个事务必须是不可分割的最小工作单元,整个操作要么全部成功,要么全部失败,一般就是通过commit和rollback来控制(开启:start transaction或者begin)
Consistency(一致性):
数据库总能从一个一致性的状态转换到另一个一致性的状态,比如老王减少100元,冰冰增加200元就是不符合一致性,但是符合原子性
Isolation(隔离性):
一个事务相对于另一个事务是隔离的,一个事务所做的修改是在最终提交以前,对其他事务是不可见的 读未提交、读已提交、可重复度、可串行化
Durability(持久性):
一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失
Sequelize执行事务
非托管事务:提交和回滚事务由用户手动完成
// 评论
app.get('/comment', async (req, res) => {
// 1.开始一个事务并将其保存到变量中
const t = await sequelize.transaction()
try {
// 2.事务作为参数传递到数据库操作中
await Comment.create({ content: '课程讲解得很详细', order_num: '345' }, { transaction: t })
await ProductOrder.update({ is_comment: 1 }, { where: { order_num: '345' }, transaction: t })
// 3.如没有引发任何错误,提交事务
await t.commit()
res.send('成功')
} catch (err) {
// 3.如引发错误,回滚事务
await t.rollback()
res.send('失败')
}
});
- 托管事务:提交和回滚事务由Sequelize 自动完成
try {
await sequelize.transaction(async (t) => {
await Comment.create({ content: '课程讲解得很详细', order_num: '345' }, { transaction: t })
await ProductOrder.update({ is_comment: 1 }, { where: { order_num: '345' }, transaction: t })
});
} catch (error) {}
530

被折叠的 条评论
为什么被折叠?



