Express中使用Sequelize实现ORM
起步
第一步当然是环境,首先使用Express生成器安装express环境
express myapp // myapp,你自己的项目名称(需要全局安装express)
npm install
然后安装sequelize
npm install --save sequelize
npm install --save mysql2 // 驱动,这里主要说mysql,其他的类型见官网文档
连接
连接到数据库必须有sequelize实例,实例化方法如下
const connect = new DB('dbname', 'username', 'password', {
host: 'localhost',
dialect: 'mysql'
})
配置好实例之后可以使用.authenticate()
来测试连接
connect.authenticate().then(() => {
console.log('连接成功')
}).catch(error => {
console.error('连接失败:', error);
})
关闭连接
默认情况下,Sequelize将使连接保持打开状态,并对所有查询使用相同的连接。如果需要关闭连接,请调用
sequelize.close()
(它是异步的并返回Promise)
模型基础
定义模型
模型是Sequelize的本质。模型是代表数据库中表的抽象。在Sequelize中,它是扩展Model的类
使用sequelize.define
方法来定义模型,sequelize会根据定义的模型名称的复数自动建表
const Book = connect.define('Book', {
bookName: DB.STRING, // 属性名: 数据类型
bookCounts: DB.INTEGER,
detail: DB.STRING,
}, {
timestamps: false // 自动生成createAt和updateAt
})
此外也可以直接提供表名
sequelize.define('Book', {
// ... attributes
}, {
tableName: 'literature'
});
更多数据类型:
// CHAR
Sequelize.STRING // VARCHAR(255)
Sequelize.STRING(1234) // VARCHAR(1234)
Sequelize.STRING.BINARY // VARCHAR BINARY
Sequelize.TEXT // TEXT
Sequelize.TEXT('tiny') // TINYTEXT
// NUMBER
Sequelize.INTEGER // INTEGER
Sequelize.BIGINT // BIGINT
Sequelize.BIGINT(11) // BIGINT(11)
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)
// TIME
Sequelize.DATE // mysql / sqlite 为 DATETIME, postgres 为带时区的 TIMESTAMP
Sequelize.DATE(6) // DATETIME(6) 适用 mysql 5.6.4+. 小数秒支持最多6位精度
Sequelize.DATEONLY // DATE 不带时间.
// BOOLEAN
Sequelize.BOOLEAN // TINYINT(1)
//ENUM
Sequelize.ENUM('value 1', 'value 2') // 一个允许值为'value 1'和'value 2'的ENUM
// blob
Sequelize.BLOB // BLOB (PostgreSQL 为 bytea)
Sequelize.BLOB('tiny') // TINYBLOB (PostgreSQL 为 bytea. 其余参数是 medium 和 long)
// GEOMETRY
Sequelize.GEOMETRY // Spatial 列. 仅 PostgreSQL (带有 PostGIS) 或 MySQL.
Sequelize.GEOMETRY('POINT') // 带有 geometry 类型的 spatial 列. 仅 PostgreSQL (带有 PostGIS) 或 MySQL.
Sequelize.GEOMETRY('POINT', 4326) // 具有 geometry 类型和 SRID 的 spatial 列. 仅 PostgreSQL (带有 PostGIS) 或 MySQL.
// unsigned 和 zerofill 属性
Sequelize.INTEGER.UNSIGNED // INTEGER UNSIGNED
Sequelize.INTEGER(11).UNSIGNED // INTEGER(11) UNSIGNED
Sequelize.INTEGER(11).ZEROFILL // INTEGER(11) ZEROFILL
Sequelize.INTEGER(11).ZEROFILL.UNSIGNED // INTEGER(11) UNSIGNED ZEROFILL
Sequelize.INTEGER(11).UNSIGNED.ZEROFILL // INTEGER(11) UNSIGNED ZEROFILL
数据类型来源,掘金,云影sky的详细易用的 Sequelize 解读
模型同步
使用model.async()方法来将模型与数据库同步
User.sync()
-如果不存在则创建表(如果已经存在则不执行任何操作)User.sync({ force: true })
-这将创建表,如果该表已经存在,则将其首先删除User.sync({ alter: true })
-这将检查数据库中表的当前状态(它具有哪些列,它们的数据类型等),然后在表中进行必要的更改以使其与模型匹配
创建模型实例
使用model.build
方法来创建模型实例
const jsBook = Book.build({
bookName: '你不知道的JS',
bookCounts: 3,
detail: 'JS 进阶系列',
})
上面的创建实例之后使用jsBook.save();
方法来保存到数据库
模型查询
INSERT查询
上面的模型保存还有一种简便方法,直接使用model.create
方法,直接保存到数据库
Book.create({
bookName: '你不知道的JS',
bookCounts: 3,
detail: 'JS 进阶系列',
})
可以看到数据库中已经生成了这条记录
控制台可以看到sql语句
SELECT查询
find查询
使用findAll
方法查询整个表
Book.findAll()
效果图
可以使用attributes
选项来进行列查询,数组中列出要查询的字段名
Book.findAll({
attributes: ['id', 'bookName'],
})
效果图
使用exclude
删除一些选定的属性
Book.findAll({
attributes: { exclude: ['bookCounts'] },
})
效果图
其他find查询
findByPk:使用提供的主键仅从表中获得一个条目
findOne:获取它找到的第一个条目(如果提供的话,它满足可选的查询选项)
findOrCreate:查询不到实例就创建一个,返回值是实例(查到的或者创建的)和一个布尔值(创建为true)
findAndCountAll:查询并计数,有两个返回值,一个是查询到的记录另一个是count
where子句
使用where
选项可以进行where查询
Book.findAll({
where: {
bookName: '你不知道的JS',
id: 1
}
})
// SELECT * FROM books WHERE bookName = '你不知道的JS' AND id = 1;
效果如图
有了AND就有OR,使用Op.or
来进行or操作
Book.findAll({
where: {
bookName: '你不知道的JS',
id: {
[Op.or]: [1, 2]
}
}
})
// SELECT * FROM books WHERE bookName = '你不知道的JS' AND (id = 1 OR id = 2);
效果图
AND也可以使用Op.and来操作,但是易读性不强(不常用)
Book.findAll({
where: {
[Op.and]: [
{ bookName: '你不知道的JS' },
{
id: {
[Op.or]: [1, 2]
}
}
]
}
})
sequelize提供了更多运算
const { Op } = require("sequelize");
Post.findAll({
where: {
[Op.and]: [{ a: 5 }, { b: 6 }], // (a = 5) AND (b = 6)
[Op.or]: [{ a: 5 }, { b: 6 }], // (a = 5) OR (b = 6)
someAttribute: {
// Basics
[Op.eq]: 3, // = 3
[Op.ne]: 20, // != 20
[Op.is]: null, // IS NULL
[Op.not]: true, // IS NOT TRUE
[Op.or]: [5, 6], // (someAttribute = 5) OR (someAttribute = 6)
// Using dialect specific column identifiers (PG in the following example):
[Op.col]: 'user.organization_id', // = "user"."organization_id"
// Number comparisons
[Op.gt]: 6, // > 6
[Op.gte]: 6, // >= 6
[Op.lt]: 10, // < 10
[Op.lte]: 10, // <= 10
[Op.between]: [6, 10], // BETWEEN 6 AND 10
[Op.notBetween]: [11, 15], // NOT BETWEEN 11 AND 15
// Other operators
[Op.all]: sequelize.literal('SELECT 1'), // > ALL (SELECT 1)
[Op.in]: [1, 2], // IN [1, 2]
[Op.notIn]: [1, 2], // NOT IN [1, 2]
[Op.like]: '%hat', // LIKE '%hat'
[Op.notLike]: '%hat', // NOT LIKE '%hat'
[Op.startsWith]: 'hat', // LIKE 'hat%'
[Op.endsWith]: 'hat', // LIKE '%hat'
[Op.substring]: 'hat', // LIKE '%hat%'
[Op.iLike]: '%hat', // ILIKE '%hat' (case insensitive) (PG only)
[Op.notILike]: '%hat', // NOT ILIKE '%hat' (PG only)
[Op.regexp]: '^[h|a|t]', // REGEXP/~ '^[h|a|t]' (MySQL/PG only)
[Op.notRegexp]: '^[h|a|t]', // NOT REGEXP/!~ '^[h|a|t]' (MySQL/PG only)
[Op.iRegexp]: '^[h|a|t]', // ~* '^[h|a|t]' (PG only)
[Op.notIRegexp]: '^[h|a|t]', // !~* '^[h|a|t]' (PG only)
[Op.any]: [2, 3], // ANY ARRAY[2, 3]::INTEGER (PG only)
// In Postgres, Op.like/Op.iLike/Op.notLike can be combined to Op.any:
[Op.like]: { [Op.any]: ['cat', 'hat'] } // LIKE ANY ARRAY['cat', 'hat']
// There are more postgres-only range operators, see below
}
}
});
UPDATE查询
使用model.update
方法来进行数据更新
Book.update({
bookCounts: 5
}, {
where: {
id: 2
}
})
// UPDATE books SET bookCounts =5 WHERE id = 2;
修改后的数据如下
DELETE查询
使用model.destory
方法进行删除操作
Book.destory({
where: {
id: 2
}
})
限制和分页
使用limit
和offset
选项进行限制/分页
- limit:每一页的记录数量限制
- offset:第几页,从0开始
Book.findAll({
where: {
bookName: '你不知道的JS',
},
offset: parseInt(req.query.page) ? parseInt(req.query.page) : 0,
limit: 1
})
实用方法
进阶用法
getter&setter
事务