Sequelize模型之间存在关联关系,这些关系代表了数据库中对应表之间的主/外键关系。基于模型关系可以实现关联表之间的连接查询、更新、删除等操作。本文将通过一个示例,介绍模型的定义,创建模型关联关系,模型与关联关系同步数据库,及关系模型的增、删、改、查操作。
1. 模型(表)之间的关联关系
1.1 模型关系概述
数据库中的表之间存在一定的关联关系,表之间的关系基于主/外键进行关联、创建约束等。关系表中的数据分为1对1(1:1)、1对多(1:M)、多对多(N:M)三种关联关系。
在Sequelize中建立关联关系,通过调用模型(源模型)的belongsTo、hasOne、hasMany、belongsToMany方法,再将要建立关系的模型(目标模型)做为参数传入即可。这些方法会按以下规则创建关联关系:
1.2 定义关系模型
为了能够清楚说明模型关系的定义及关系模型的使用,我们定义如下4个模型对象:
用户(User)-与其它模型存在1:1、1:N、N:M
用户登录信息(UserCheckin)-与User存在1:1关系
用户地址(UserAddress)-与User存在N:1关系
角色(Role)-与User存在N:M关系
这几个模型的E-R结构如下:
定义User模型如下:
module.exports = function (sequelize, DataTypes) {
return sequelize.define('User', {
id:{type:DataTypes.BIGINT(11), autoIncrement:true, primaryKey : true, unique : true},
username: { type: DataTypes.STRING, allowNull: false, comment:'用户名' },
password: { type: DataTypes.STRING, allowNull: false, comment:'用户密码' },
active: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: true, comment:'是否正常状态' }
},
{
timestamps: true,
underscored: true,
paranoid: true,
freezeTableName: true,
tableName: 'user',
charset: 'utf8',
collate: 'utf8_general_ci'
});
}
在这个模型中,配置模型时,我们使用了以下配置:
timestamps: true-时间戳,启用该配置后会自动添加createdAt、updatedAt两个字段,分别表示创建和更新时间
underscored: true-使用下划线,自动添加的字段会在数据段中使用“蛇型命名”规则,如:createdAt在数据库中的字段名会是created_at
paranoid: true-虚拟删除。启用该配置后,数据不会真实删除,而是添加一个deletedAt属性
更多关于模型配置,请参考:配置模型。
module.exports = function (sequelize, DataTypes) {
return sequelize.define('UserCheckin', {
id: { type: DataTypes.BIGINT(11), autoIncrement: true, primaryKey: true, unique: true },
userId: {
type: DataTypes.BIGINT(11),
field: 'user_id',
unique: true,
references: {
model: 'User',
key: 'id'
},
comment:'用户Id' },
loginIp: { type: DataTypes.STRING, field: 'login_ip', allowNull: false, defaultValue: '' , validate: {isIP: true}, comment:'登录IP'}
},
{
underscored: true,
timestamps: true,
tableName: 'userCheckin',
comment: '用户登录信息',
charset: 'utf8',
collate: 'utf8_general_ci',
indexes: [{
name: 'userCheckin_userId',
method: 'BTREE',
fields: ['user_id']
}]
});
}
在定义这个模型时,我们通过references特性将userId定义为外键,并通过field特性将其在数据库中的字段名指定为user_id。
module.exports = function (sequelize, DataTypes) {
return sequelize.define('UserAddress', {
id: { type: DataTypes.BIGINT(11), autoIncrement: true, primaryKey: true, unique: true, comment:'主键' },
userId: {type: DataTypes.BIGINT(11), field: 'user_id', allowNull: false, comment:'用户Id' },
consignee : { type: DataTypes.STRING, field: 'consignee', allowNull: false, comment:'收货人' },
address: { type: