跳至主要内容
版本:v6 - 稳定版

模型实例

如您所知,模型是 ES6 类。类的实例表示该模型中的一个对象(映射到数据库中表的一行)。这样,模型实例就是 DAO

本指南假设以下设置

const { Sequelize, Model, DataTypes } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory:');

const User = sequelize.define('user', {
name: DataTypes.TEXT,
favoriteColor: {
type: DataTypes.TEXT,
defaultValue: 'green',
},
age: DataTypes.INTEGER,
cash: DataTypes.INTEGER,
});

(async () => {
await sequelize.sync({ force: true });
// Code here
})();

创建实例

虽然模型是一个类,但您不应该直接使用 new 运算符创建实例。相反,应该使用 build 方法

const jane = User.build({ name: 'Jane' });
console.log(jane instanceof User); // true
console.log(jane.name); // "Jane"

然而,上面的代码根本没有与数据库通信(请注意它甚至不是异步的)!这是因为 build 方法只创建一个对象,该对象表示可以映射到数据库的数据。为了真正将该实例保存(即持久化)到数据库中,应该使用 save 方法

await jane.save();
console.log('Jane was saved to the database!');

请注意,从上面代码段中 await 的使用可以看出,save 是一个异步方法。事实上,几乎每个 Sequelize 方法都是异步的;build 是为数不多的例外之一。

一个非常有用的快捷方式:create 方法

Sequelize 提供了 create 方法,它将上面显示的 buildsave 方法组合成一个单一方法

const jane = await User.create({ name: 'Jane' });
// Jane exists in the database now!
console.log(jane instanceof User); // true
console.log(jane.name); // "Jane"

注意:记录实例

尝试直接将模型实例记录到 console.log 将会产生很多杂乱信息,因为 Sequelize 实例附带了很多内容。相反,您可以使用 .toJSON() 方法(顺便说一下,该方法会自动保证实例能够被 JSON.stringify 正确地序列化)。

const jane = await User.create({ name: 'Jane' });
// console.log(jane); // Don't do this
console.log(jane.toJSON()); // This is good!
console.log(JSON.stringify(jane, null, 4)); // This is also good!

默认值

构建的实例会自动获得默认值

const jane = User.build({ name: 'Jane' });
console.log(jane.favoriteColor); // "green"

更新实例

如果您更改了实例中某个字段的值,再次调用 save 将相应地更新它

const jane = await User.create({ name: 'Jane' });
console.log(jane.name); // "Jane"
jane.name = 'Ada';
// the name is still "Jane" in the database
await jane.save();
// Now the name was updated to "Ada" in the database!

您可以使用 set 方法一次更新多个字段

const jane = await User.create({ name: 'Jane' });

jane.set({
name: 'Ada',
favoriteColor: 'blue',
});
// As above, the database still has "Jane" and "green"
await jane.save();
// The database now has "Ada" and "blue" for name and favorite color

请注意,此处的 save() 还会持久化对该实例所做的任何其他更改,而不仅仅是之前 set 调用中的更改。如果您想更新特定的一组字段,可以使用 update

const jane = await User.create({ name: 'Jane' });
jane.favoriteColor = 'blue';
await jane.update({ name: 'Ada' });
// The database now has "Ada" for name, but still has the default "green" for favorite color
await jane.save();
// Now the database has "Ada" for name and "blue" for favorite color

删除实例

您可以通过调用 destroy 删除实例

const jane = await User.create({ name: 'Jane' });
console.log(jane.name); // "Jane"
await jane.destroy();
// Now this entry was removed from the database

重新加载实例

您可以通过调用 reload 从数据库中重新加载实例

const jane = await User.create({ name: 'Jane' });
console.log(jane.name); // "Jane"
jane.name = 'Ada';
// the name is still "Jane" in the database
await jane.reload();
console.log(jane.name); // "Jane"

重新加载调用会生成一个 SELECT 查询,以从数据库获取最新的数据。

仅保存某些字段

可以通过传递一个列名数组来定义调用 save 时应保存哪些属性。

当您根据之前定义的对象设置属性时,例如,当您通过 Web 应用程序的表单获取对象的 value 时,这很有用。此外,这在 update 实现中被内部使用。它是这样的

const jane = await User.create({ name: 'Jane' });
console.log(jane.name); // "Jane"
console.log(jane.favoriteColor); // "green"
jane.name = 'Jane II';
jane.favoriteColor = 'blue';
await jane.save({ fields: ['name'] });
console.log(jane.name); // "Jane II"
console.log(jane.favoriteColor); // "blue"
// The above printed blue because the local object has it set to blue, but
// in the database it is still "green":
await jane.reload();
console.log(jane.name); // "Jane II"
console.log(jane.favoriteColor); // "green"

save 的更改感知

save 方法在内部进行了优化,只更新真正改变的字段。这意味着如果您没有进行任何更改并调用 save,Sequelize 会知道保存是多余的并且不做任何操作,即不会生成任何查询(它仍然会返回一个 Promise,但它会立即解析)。

此外,如果您调用 save 时只更改了几个属性,那么只有这些字段将在 UPDATE 查询中发送,以提高性能。

递增和递减整数值

为了在不出现并发问题的情况下递增/递减实例的值,Sequelize 提供了 incrementdecrement 实例方法。

const jane = await User.create({ name: 'Jane', age: 100 });
const incrementResult = await jane.increment('age', { by: 2 });
// Note: to increment by 1 you can omit the `by` option and just do `user.increment('age')`

// In PostgreSQL, `incrementResult` will be the updated user, unless the option
// `{ returning: false }` was set (and then it will be undefined).

// In other dialects, `incrementResult` will be undefined. If you need the updated instance, you will have to call `user.reload()`.

您也可以一次递增多个字段

const jane = await User.create({ name: 'Jane', age: 100, cash: 5000 });
await jane.increment({
age: 2,
cash: 100,
});

// If the values are incremented by the same amount, you can use this other syntax as well:
await jane.increment(['age', 'cash'], { by: 2 });

递减的工作方式完全相同。