模型实例
如你所知,型号是 ES6 类。该类的一个实例代表该模型中的一个对象(映射到数据库中表的一行)。这样,模型实例就是 DAO。
¥As you already know, a model is an ES6 class. An instance of the class represents one object from that model (which maps to one row of the table in the database). This way, model instances are DAOs.
对于本指南,将假定以下设置:
¥For this guide, the following setup will be assumed:
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
})();
创建实例
¥Creating an instance
尽管模型是一个类,但你不应该直接使用 new
运算符创建实例。相反,应该使用 build
方法:
¥Although a model is a class, you should not create instances by using the new
operator directly. Instead, the build
method should be used:
const jane = User.build({ name: 'Jane' });
console.log(jane instanceof User); // true
console.log(jane.name); // "Jane"
然而,上面的代码根本不与数据库通信(注意,它甚至不是异步的)!这是因为 build
方法仅创建一个表示可以映射到数据库的数据的对象。为了真正将该实例保存(即持久)到数据库中,应使用 save
方法:
¥However, the code above does not communicate with the database at all (note that it is not even asynchronous)! This is because the build
method only creates an object that represents data that can be mapped to a database. In order to really save (i.e. persist) this instance in the database, the save
method should be used:
await jane.save();
console.log('Jane was saved to the database!');
请注意,从上面代码片段中 await
的用法来看,save
是一个异步方法。事实上,几乎每个 Sequelize 方法都是异步的;build
是极少数的例外之一。
¥Note, from the usage of await
in the snippet above, that save
is an asynchronous method. In fact, almost every Sequelize method is asynchronous; build
is one of the very few exceptions.
一个非常有用的快捷方式:create
方法
¥A very useful shortcut: the create
method
Sequelize 提供了 create
方法,它将上面显示的 build
和 save
方法组合成一个方法:
¥Sequelize provides the create
method, which combines the build
and save
methods shown above into a single method:
const jane = await User.create({ name: 'Jane' });
// Jane exists in the database now!
console.log(jane instanceof User); // true
console.log(jane.name); // "Jane"
注意:记录实例
¥Note: logging instances
尝试将模型实例直接记录到 console.log
会产生很多混乱,因为 Sequelize 实例附加了很多东西。相反,你可以使用 .toJSON()
方法(顺便说一下,它会自动保证实例能够很好地进行 JSON.stringify
处理)。
¥Trying to log a model instance directly to console.log
will produce a lot of clutter, since Sequelize instances have a lot of things attached to them. Instead, you can use the .toJSON()
method (which, by the way, automatically guarantees the instances to be JSON.stringify
-ed well).
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!
默认值
¥Default values
构建的实例将自动获取默认值:
¥Built instances will automatically get default values:
const jane = User.build({ name: 'Jane' });
console.log(jane.favoriteColor); // "green"
更新实例
¥Updating an instance
如果更改实例的某个字段的值,再次调用 save
将会相应更新:
¥If you change the value of some field of an instance, calling save
again will update it accordingly:
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
方法一次更新多个字段:
¥You can update several fields at once with the set
method:
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
:
¥Note that the save()
here will also persist any other changes that have been made on this instance, not just those in the previous set
call. If you want to update a specific set of fields, you can use 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
删除实例
¥Deleting an instance
你可以通过调用 destroy
来删除实例:
¥You can delete an instance by calling destroy
:
const jane = await User.create({ name: 'Jane' });
console.log(jane.name); // "Jane"
await jane.destroy();
// Now this entry was removed from the database
重新加载实例
¥Reloading an instance
你可以通过调用 reload
从数据库重新加载实例:
¥You can reload an instance from the database by calling 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
查询以从数据库获取最新数据。
¥The reload call generates a SELECT
query to get the up-to-date data from the database.
只保存部分字段
¥Saving only some fields
可以通过传递列名数组来定义调用 save
时应保存哪些属性。
¥It is possible to define which attributes should be saved when calling save
, by passing an array of column names.
当你根据先前定义的对象设置属性时(例如,当你通过 Web 应用的表单获取对象的值时),这非常有用。此外,这在 update
实现中内部使用。它是这样的:
¥This is useful when you set attributes based on a previously defined object, for example, when you get the values of an object via a form of a web app. Furthermore, this is used internally in the update
implementation. This is how it looks like:
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"
保存的变化意识
¥Change-awareness of save
save
方法在内部进行了优化,只更新真正更改的字段。这意味着,如果你不更改任何内容并调用 save
,Sequelize 将知道保存是多余的并且不执行任何操作,即不会生成任何查询(它仍然会返回 Promise,但会立即解析)。
¥The save
method is optimized internally to only update fields that really changed. This means that if you don't change anything and call save
, Sequelize will know that the save is superfluous and do nothing, i.e., no query will be generated (it will still return a Promise, but it will resolve immediately).
此外,如果在调用 save
时仅更改了少数属性,则只有这些字段将在 UPDATE
查询中发送,以提高性能。
¥Also, if only a few attributes have changed when you call save
, only those fields will be sent in the UPDATE
query, to improve performance.
递增和递减整数值
¥Incrementing and decrementing integer values
为了增加/减少实例的值而不遇到并发问题,Sequelize 提供了 increment
和 decrement
实例方法。
¥In order to increment/decrement values of an instance without running into concurrency issues, Sequelize provides the increment
and decrement
instance methods.
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()`.
你还可以一次增加多个字段:
¥You can also increment multiple fields at once:
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 });
递减的工作方式完全相同。
¥Decrementing works in the exact same way.