模型实例
如您所知,模型是 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
方法,它将上面显示的 build
和 save
方法组合成一个单一方法
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 提供了 increment
和 decrement
实例方法。
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 });
递减的工作方式完全相同。