介绍
对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中 概述
Sequelize 是一个基于 promise 的 Node.js ORM, 目前支持 Postgres, MySQL, MariaDB, SQLite 以及 Microsoft SQL Server. 它具有强大的事务支持, 关联关系, 预读和延迟加载,读取复制等功能.
为什么选择它?
Node.js 中连接数据库需要自己建立并管理连接,操作繁琐,还需要自己编写 sql 语句。简单的项目可能还行,当项目设计的东西比较复杂,表比较多的时候,对于 sql 语句的编写就比较耗费精力。
在 Java、C# 等语言中都已经有轻量级的数据库框架或者解决方案了。在 Node.js 中可以使用 Sequelize ,它是一个很成熟的框架,在速度和性能上也非常有优势。而且关键在于,开发时只需要管理对象的创建、查询方法的调用等即可,极少需要编写 sql 语句。这样一来不仅省去了复杂的 sql 语句维护,同时也避免了因 sql 语句而引起的不必要的bug。
安装
cnpm i sequelize mysql2 -S
基本使用
连接数据库
//导入 sequelize
const Sequelize = require('sequelize');
//连接数据库
//参数:数据库 用户名 密码 配置
const sequelize = new Sequelize('db1', 'root', '******', {
host: 'localhost', //主机地址
dialect: 'mysql', //语言
})
测试连接
//测试连接
async function test() {
try {
await sequelize.authenticate();
console.log('Connection has been established successfully.');
} catch (error) {
console.error('Unable to connect to the database:', error);
}
}
test();
模型同步
通过调用一个异步函数(返回一个Promise)model.sync(options)
. 通过此调用,Sequelize 将自动对数据库执行 SQL 查询.
Books.sync()
- 如果表不存在,则创建该表(如果已经存在,则不执行任何操作)Books.sync({ force: true })
- 将创建表,如果表已经存在,则将其首先删除Books.sync({ alter: true })
- 这将检查数据库中表的当前状态(它具有哪些列,它们的数据类型等),然后在表中进行必要的更改以使其与模型匹配
创建模型(表)并添加到数据库
//定义模型
const Books = sequelize.define('books' /* 自定义表名 */ , {
// 定义表中的字段,对象中的属性
id: {
type: Sequelize.INTEGER, //定义数据类型
primaryKey: true, //设置主键
autoIncrement: true, //设置自动增长
comment: '自增id', //添加描述
},
name: {
type: Sequelize.STRING,
allowNull: false, //是否允许为空,默认为true
},
price: {
type: Sequelize.FLOAT,
allowNull: false,
},
count: {
type: Sequelize.INTEGER,
defaultValue: 0, //设置默认值
}
}, {
// 其他模型参数
timestamps: false, //禁用时间戳,去掉createdAt和updatedAt字段,默认为true
freezeTableName: true, //表名冻结,Model对应的表名将与定义的'books'相同,默认为true
});
//模型同步,迁移模型映射到数据库
Books.sync({
force: true //将创建表,如果表已经存在,则将其首先删除
})
一次同步所有模型
可以使用 sequelize.sync()
自动同步所有模型.
await sequelize.sync({ force: true });
console.log("所有模型均已成功同步.");
更多数据类型
字符串
Sequelize.STRING // VARCHAR(255),默认长度255
Sequelize.STRING(1234) // VARCHAR(1234),指定长度的字符串
Sequelize.STRING.BINARY // VARCHAR BINARY
Sequelize.TEXT // TEXT,文本字符串
Sequelize.TEXT('tiny') // TINYTEXT,小文本字符串
布尔
Sequelize.BOOLEAN // TINYINT(1),小int类型,长度为1(0,1)
数字
Sequelize.INTEGER // INTEGER,int类型
Sequelize.BIGINT // BIGINT,更大的int类型
Sequelize.BIGINT(11) // BIGINT(11),指定长度的BIGINT
Sequelize.FLOAT // FLOAT,浮点类型
Sequelize.FLOAT(11) // FLOAT(11),指定长度的浮点类型
Sequelize.FLOAT(11, 10) // FLOAT(11,10),指定长度和小数点后的位数
Sequelize.DOUBLE // DOUBLE
Sequelize.DOUBLE(11) // DOUBLE(11)
Sequelize.DOUBLE(11, 10) // DOUBLE(11,10)
Sequelize.DECIMAL // DECIMAL,更准确的小数点类型
Sequelize.DECIMAL(10, 2) // DECIMAL(10,2),指定长度和小数点后的位数
日期
Sequelize.DATE // DATETIME 适用于 mysql / sqlite, 带时区的TIMESTAMP 适用于 postgres
Sequelize.DATE(6) // DATETIME(6) 适用于 mysql 5.6.4+. 支持6位精度的小数秒
Sequelize.DATEONLY // 不带时间的 DATE,仅日期部分
枚举
Sequelize.ENUM('value 1','value 2','value 3') //枚举类型,从 value 1、value 2、value 3中取
JSON
Sequelize.JSON //适用于 mysql 5.7.8+ ,JSON类型
删除表
删除与模型相关的表:
await Books.drop();
console.log("用户表已删除!");
删除所有表:
await sequelize.drop();
console.log("所有表已删除!");
增删查改
增
插入一条数据使用create({})
.
Books.sync({
force: true //将创建表,如果表已经存在,则将其首先删除
}).then(() => {
//插入一条数据使用 create({})
return Books.create({
name: 'JavaScript编程',
price: '36.6',
count: 14
})
})
插入多条数据使用bulkCreate([{},{}])
.
Books.sync({
force: true //将创建表,如果表已经存在,则将其首先删除
}).then(() => {
//插入多条数据使用 bulkCreate([{},{}])
return Books.bulkCreate([{
name: 'JavaScript编程',
price: 36.6,
count: 36
}, {
name: 'Vue实战开发',
price: 99.9,
count: 64
}, {
name: 'React实战开发',
price: 128.6,
count: 87
}, {
name: 'Node.js实战',
price: 136.2,
count: 59
}])
})
查
查询所有数据使用Books.findAll()
.
Books.findAll().then(books => {
console.log('all books', JSON.stringify(books, null, 4)); //使用四个空格缩进
//计算总价格
console.log(books[0].price*50);
})
查询一条数据使用Books.findOne()
.
//查询一条数据
Books.findOne().then(books => {
console.log(JSON.stringify(books, null, 4));
})
默认查询第1条数据,可在findOne()
中指定查询的条件
Books.findOne({
where: {
id: 2
}
}).then(books => {
console.log(JSON.stringify(books, null, 4));
})
更多的查询操作
具体参考:sequelize模型查询
//导入 Op
const Op = Sequelize.Op;
Books.findAll({
//SELECT `name`, `price` FROM `books` AS `books` WHERE
//`books`.`price` > '40' ORDER BY `books`.`id` DESC LIMIT 2;
where: {
price: {
//价格大于40
//SELECT `id`, `name`, `price`, `count` FROM `books` AS `books`
//WHERE `books`.`price` > '40';
[Op.gt]: 40,
},
},
order: [
['id', 'DESC'], //按id,倒序
],
limit: 2, //返回的个数
// attributes: ['name', 'price'], //查询特定属性,只要 name 和 price
attributes: {
exclude: ['id', 'name'] //查询特定属性,不包含 id 和 name
},
}).then(books => {
console.log('all books', JSON.stringify(books, null, 4)); //使用四个空格缩进
})
聚合函数
//count 方法仅计算数据库中元素出现的次数.
Books.count('id').then(counts => console.log(counts));
//max 方法获取数据库中元素的最大值
Books.max('price').then(maxPrice => console.log(maxPrice));
//min 方法获取数据库中元素的最小值
Books.min('price').then(minPrice => console.log(minPrice));
//sum 方法获取数据库中元素的总和
Books.sum('count').then(sum => console.log(sum));
扩展
有时候在获取之后可能还需要进行一些其他的操作,比如说:计算总价格
books[0].price*购买的数量
,但是每次都这样操作,不方便,可以考虑扩展一些方法。
实例扩展
在Books的原型上扩展一个计算总价格的方法
//实例扩展
Books.prototype.totalPrice = function (count) {
return this.price * count;
}
Books.findAll().then(books => {
console.log('all books', JSON.stringify(books, null, 4)); //使用四个空格缩进
//直接调用原型上的方法即可
console.log(books[0].totalPrice(50));
})
模型扩展
直接在Books上扩展方法
//模型扩展
Books.classify = function (name) {
const XHPublisher = ['JavaScript编程', 'Node.js实战'];
return XHPublisher.includes(name) ? '新华出版社' : '其他出版社';
}
const arr = ['React实战开发', 'JavaScript编程', 'Vue实战开发'];
arr.forEach(item => {
//获取每一本书的出版社
console.log(Books.classify(item));
})
改
//更新
Books.update({
//UPDATE `books` SET `price`=? WHERE `id` = ?
//要修改的值
price: 50
}, {
//条件
where: {
id: 1
}
})
删
//删除
Books.destroy({
//条件
where: {
id: 4
}
})