sequelize
定义:Sequelize是一款基于Nodejs功能强大的异步ORM框架。同时支持PostgreSQL, MySQL, SQLite and MSSQL多种数据库,很适合作为Nodejs后端数据库的存储接口,为快速开发Nodejs应用奠定扎实、安全的基础
连接postgresql
创建连接
const Sequelize = require('sequelize')
const sequelize = new Sequelize('database', 'username', 'password', {
host: 'localhost',
dialect: /* 'mysql' | 'mariadb' | 'postgres' | 'mssql' 之一 */,
});
//使用连接池
pool: {
max: 5,
min: 0,
acquire: 30000, //该池在抛出错误之前将尝试获得连接的最长时间(以毫秒为单位)
idle: 10000 //连接释放之前可以空闲的最长时间(以毫秒为单位)
}
定义模型
第一种:使用Sequelize.Model类中的init()
const Model = Sequelize.Model;
class User extends Model {}
User.init({
// 属性
firstName: {
type: Sequelize.STRING,
allowNull: false
},
lastName: {
type: Sequelize.STRING
// allowNull 默认为 true
}
}, {
sequelize,
modelName: 'user'
// 参数
});
第二种:sequelize.define【内部调用了init()】
const User = sequelize.define('user', {
// 属性
firstName: {
type: Sequelize.STRING,
allowNull: false
},
lastName: {
type: Sequelize.STRING
// allowNull 默认为 true
}
}, {
// 参数
});
将模型与数据库同步
sequelize.sync({
force: true|false //当为true时,先删除表后再创建
})
sequelize操作数据库
添加单条记录
animal.create({
name: '小鸡',
age: 2
}).then(result => {
console.log(JSON.stringify(result))
}).catch(err => {
console.log(err)
})
批量添加
animal.bulkCreate([
{name: '知了',age:16},
{name: '羊',age:14}
]).then(function (p) {
console.log('created. ' + JSON.stringify(p));
}).catch(function (err) {
console.log('failed: ' + err);
})
修改数据
animal.update(
{name:'蚂蚁'},
{where:{id:[4,8]}}
).then(([affectedCount])=>{
console.log('受影响的数量'+affectedCount)
}).catch(err=>{
console.log(err)
})
删除数据
animal.destroy({
where: {
id:{[Op.gt]:35}
}
}).then(affectedRows => {
console.log(affectedRows)
}).catch(err=>{
console.log(err)
})
查询数据
Hooks
Hook(也称为生命周期事件)是执行 sequelize 调用之前和之后调用的函数
添加Hooks的三种方式
第一种方式
class Order extends Model{}
Order.init({
orderName:DataTypes.STRING,
remark:{
type:DataTypes.ENUM,
values:['好用','美观','便宜']
}
},{
hooks:{
beforeValidate:(order,options)=>{
order.remark = '好用'
},
afterValidate:(order,options)=>{
order.orderName = '牙刷'
}
},sequelize
})
第二种方式
class Order extends Model{}
Order.init({
orderName:DataTypes.STRING,
remark:{
type:DataTypes.ENUM,
values:['好用','美观','便宜']
}
},{
sequelize
})
Order.addHook('beforeValidate',(order,options)=>{
order.remark = '好用'
})
Order.addHook('afterValidate','someCustomName',(order,options)=>{
return Promise.reject(new Error("you can not do that"))
})
第三种方式
class Order extends Model{}
Order.init({
orderName:DataTypes.STRING,
password:DataTypes.STRING,
remark:{
type:DataTypes.ENUM,
values:['好用','美观','便宜']
}
},{
sequelize
})
Order.beforeCreate((order,options)=>{
return hashPassword(order.password).then(hashedPw=>{
order.password = hashedPw
})
})
Order.afterValidate('myHookAfter',(order,options)=>{
order.orderName = '毛巾'
})
Removing hooks移除 Hook
只能删除有名称参数的 hook.
Order.addHook('afterValidate','someCustomName',(order,options)=>{
return Promise.reject(new Error("you can not do that"))
})
Order.removeHook('afterValidate','someCustomName')
Global hooks全局 Hooks
//定义一个全局hook
const sequelize = new Sequelize(..., {
define: {
hooks: {
beforeCreate: () => {
// 做些什么
}
}
}
});
案例
class User extends Model {}
User.init({}, { sequelize });
class Project extends Model {}
Project.init({}, {
hooks: {
beforeCreate: () => {
//
}
},
sequelize
});
User.create() // 运行全局 hook
Project.create() // 运行其自身的 hook (因为全局 hook 被覆盖)
Permanent Hooks常驻 Hooks
无论模型是否指定了自己的 beforeCreate
hook.本地 hook 总是在全局 hook 之前运行::
//定义一个常驻Hook
sequelize.addHook('beforeCreate', () => {
// 做些什么
});
案例
class User extends Model {}
User.init({}, { sequelize });
class Project extends Model {}
Project.init({}, {
hooks: {
beforeCreate: () => {
// 做些其它什么
}
},
sequelize
});
User.create() // 运行全局 hook
Project.create() //运行其自己的 hook 之后运行全局 hook
关联
一对一
使用belongsTo或者haveOne,belogsTo是将关联键添加到前者模型中,haveOne相反
//一对一关联
class Player extends Model {}
Player.init({/* attributes */}, { sequelize, modelName: 'player' });
class Team extends Model {}
Team.init({/* attributes */}, { sequelize, modelName: 'team' });
Player.belongsTo(Team);
//Player.hasOne(Team);
Foreign keys 外键
自定义的外键使用foreignKey,原本默认会将conmpany_id添加到user中,现在就会将fk_company添加到user中。underscored:true字段会用下划线的格式默认使用驼峰原则
class User extends Model {}
User.init({/* attributes */}, { sequelize, modelName: 'user',underscored:true })
class Company extends Model {}
Company.init({/* attributes */}, { sequelize, modelName: 'company' });
User.belongsTo(Company, {foreignKey: 'fk_company'});
Target keys 目标键
目标键是源模型上的外键列指向的目标模型上的列. 默认情况下,belongsTo 关系的目标键将是目标模型的主键. 要定义自定义列,使用 targetKey
class User extends Model {}
User.init({
id:{
type:Sequelize.INTEGER,
primaryKey:true,
unique: true
}},{ sequelize, modelName: 'user' })
class Company extends Model {}
Company.init({
name:{
type:Sequelize.STRING,
unique: true
}},{ sequelize, modelName: 'company' });
User.belongsTo(Company, {foreignKey: 'fk_companyname', targetKey: 'name'}); // 添加 fk_companyname 到 User
Source keys 源键
源关键是源模型中的属性,它是指向目标模型的外键属性. 默认情况下,hasOne
关系的源键将是源模型的主要属性. 要使用自定义属性,使用sourceKey
.
class User extends Model {}
User.init({/* attributes */}, { sequelize, modelName: 'user' })
class Company extends Model {}
Company.init({/* attributes */}, { sequelize, modelName: 'company' });
// 将 companyName 属性添加到 User
// 使用 Company 的 name 属性作为 source 属性
Company.hasOne(User, {foreignKey: 'companyName', sourceKey: 'name'});
一对多
使用hasMany
//一对多关联
class Person extends Model{}
Person.init({},{sequelize,modelName:'person'})
class Project extends Model{}
Project.init({},{sequelize,modelName:'project'})
//使用as后getPerson()、setPerson()就变成了getWorker()、setWorker()可以使用Project.prototype打印出来
Project.hasMany(Person,{as:'Worders'})
//console.log(Project.prototype)//查看project有哪些方法
多对多
使用belongsToMany
案例:会额外创建一个UserProject的表,表中包含了外键userId和projectId
class User extends Model {}
User.init({/* attributes */}, { sequelize, modelName: 'user',underscored:true })
class Project extends Model {}
Project.init({/* attributes */}, { sequelize, modelName: 'Project' });
Project.belongsToMany(User, {through: 'UserProject'});
User.belongsToMany(Project, {through: 'UserProject'});
预加载
当你从数据库检索数据时,也想同时获得与之相关联的查询,这被称为预加载.当你调用
find
或findAll
时使用include
属性.
user.findAll({ include: [ task ] }).then(([user]) => {
console.log(user.get({
plain: true
}))
})
sequelize事务
- 事务分为两种:
- 一种需要我们手动执行
commit
和rollback
命令进行提交和回滚 - 另一种是自动管理的,根据promise链的结果自动提交或回滚事物
- 一种需要我们手动执行