模型基础
在本教程中,你将学习 Sequelize 中的模型以及如何使用它们.
概念
模型是 Sequelize 的本质. 模型是代表数据库中表的抽象. 在 Sequelize 中,它是一个 Model 的扩展类.
该模型告诉 Sequelize 有关它代表的实体的几件事,例如数据库中表的名称以及它具有的列(及其数据类型).
Sequelize 中的模型有一个名称. 此名称不必与它在数据库中表示的表的名称相同. 通常,模型具有单数名称(例如,User
),而表具有复数名称(例如, Users
),当然这是完全可配置的.
模型定义
在 Sequelize 中可以用两种等效的方式定义模型:
定义模型后,可通过其模型名称在 sequelize.models
中使用该模型.
为了学习一个示例,我们将考虑创建一个代表用户的模型,该模型具有一个 firstName
和一个 lastName
. 我们希望将模型称为 User
,并将其表示的表在数据库中称为 Users
.
定义该模型的两种方法如下所示. 定义后,我们可以使用 sequelize.models.User
访问模型.
使用 sequelize.define
:
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory:');
const User = sequelize.define('User', {
// 在这里定义模型属性
firstName: {
type: DataTypes.STRING,
allowNull: false
},
lastName: {
type: DataTypes.STRING
// allowNull 默认为 true
}
}, {
// 这是其他模型参数
});
// `sequelize.define` 会返回模型
console.log(User === sequelize.models.User); // true
扩展 Model
const { Sequelize, DataTypes, Model } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory:');
class User extends Model {}
User.init({
// 在这里定义模型属性
firstName: {
type: DataTypes.STRING,
allowNull: false
},
lastName: {
type: DataTypes.STRING
// allowNull 默认为 true
}
}, {
// 这是其他模型参数
sequelize, // 我们需要传递连接实例
modelName: 'User' // 我们需要选择模型名称
});
// 定义的模型是类本身
console.log(User === sequelize.models.User); // true
在内部,sequelize.define
调用 Model.init
,因此两种方法本质上是等效的.
公共类字段的注意事项
添加与模型属性之一同名的公共类字段会出现问题. Sequelize 为通过 Model.init
定义的每个属性添加一个 getter 和一个 setter. 添加公共类字段将隐藏那些 getter 和 setter,从而阻止对模型的实际数据的访问.
// 无效的
class User extends Model {
id; // 此字段将影响 sequelize 的 getter 和 setter. 它应该被删除.
otherPublicField; // 这个字段不会影响任何东西. 没问题.
}
User.init({
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
}
}, { sequelize });
const user = new User({ id: 1 });
user.id; // undefined
// 有效的
class User extends Model {
otherPublicField;
}
User.init({
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
}
}, { sequelize });
const user = new User({ id: 1 });
user.id; // 1
在 TypeScript 中, 您可以使用 declare
关键字添加键入信息, 而无需添加实际的公共类字段:
// 有效
class User extends Model {
declare id: number; // 您可以使用 `declare` 关键字添加键入信息, 而无需添加实际的公共类字段.
}
User.init({
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
}
}, { sequelize });
const user = new User({ id: 1 });
user.id; // 1
表名推断
请注意,在以上两种方法中,都从未明确定义表名(Users
). 但是,给出了模型名称(User
).
默认情况下,当未提供表名时,Sequelize 会自动将模型名复数并将其用作表名. 这种复数是通过称为 inflection 的库在后台完成的,因此可以正确计算不规则的复数(例如 person -> people
).
当然,此行为很容易配置.
强制表名称等于模型名称
你可以使用 freezeTableName: true
参数停止 Sequelize 执行自动复数化. 这样,Sequelize 将推断表名称等于模型名称,而无需进行任何修改:
sequelize.define('User', {
// ... (属性)
}, {
freezeTableName: true
});
上面的示例将创建一个名为 User
的模型,该模型指向一个也名为 User
的表.
也可以为 sequelize 实例全局定义此行为:
const sequelize = new Sequelize('sqlite::memory:', {
define: {
freezeTableName: true
}
});
这样,所有表将使用与模型名称相同的名称.
直接提供表名
你也可以直接直接告诉 Sequelize 表名称:
sequelize.define('User', {
// ... (属性)
}, {
tableName: 'Employees'
});