跳至主要內容

模型实例

微信公众号:储凡About 14 min

模型实例

表模型是一个ES6的类,基于该类去创建的一个实例对象就是表模型实例对象,这个对象是映射到数据库表的一行,类似于Entity这种概念。 本质上模型实例是数据传输对象open in new window

这里定义一个简单的表模型,例如:

const { Sequelize, Model, DataTypes } = require('sequelize')
const sequelize = new Sequelize('postgres://user:pass@142vip.cn:5432/142vip')

/**
 * 定义用户表模型
 */
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 })
})()

创建实例

尽管模型是一个类,不应该直接使用 new 运算符来创建实例。相反,应该使用 build方法:

const user = User.build({
  name: "142vip.cn"
});

// 判断实例是否为User类创建出来
console.log(user instanceof User) // true
console.log(user.name)

上面的代码没有与数据库进行通信、操作,因为 build方法仅创建一个对象,表示可以映射到数据库的数据

如果需要将user实例保存到数据库表中,可以使用save()函数来实现持久化,例如:

// 将用户信息持久化到数据库表中
await user.save();

await 用法来看,save 是一种异步方法。实际上,几乎每个 Sequelize 方法都是异步的。 build 是极少数例外之一。

Sequelize提供了 create方法,该方法将上述的 build 方法和 save 方法合并为一个方法:

// 创建持久化对象
const user = await User.create({
  name: "142vip.cn"
});

// 信息已经写入到数据库中
console.log(user instanceof User); // true
console.log(user.name)

实例记录

将模型实例直接记录到控制台console.log 会产生很多问题。因为 Sequelize 实例具有很多附加条件。 相反,可以使用 .toJSON()方法(顺便说一句,它会自动保证实例被 JSON.stringify编辑好).

const user = await User.create({
  name: "142vip"
});

// 不建议这样输出
console.log(user);

// 推荐转化为JSON字符串输出
console.log(user.toJSON());
// 当然也推荐序列化后输出
console.log(JSON.stringify(user, null, 4)); 

注意:JSON.stringify(user, null, 4)中,三个参数的使用情况。 参考JSON.stringify()的APIopen in new window

当字段未赋值时,内置实例将自动获得默认值:

const user = User.build({
  name: "142vip.cn"
});

// favoriteColor字段的默认值为:green
console.log(user.favoriteColor); // "green"

更新实例

如果需要更改实例的某个字段的值,则再次调用 save 将相应地对其进行更新:

const user = await User.create({
  name: "142vip.cn"
});

// 当前实例name字段的值
console.log(user.name)

// 实例对象重新赋值
user.name = "微信公众号:储凡";

// 执行save()更新,数据库中的信息才会更新
await user.save();

删除实例

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

// 创建实例
const user = await User.create({
  name: "142vip.cn"
});

// 获取实例对象属性
console.log(user.name)

// 删除实例,从数据库中删除数据
await user.destroy();

实例重载

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

// 创建实例
const user = await User.create({
  name: "142vip.cn"
});

// 获取实例对象属性
console.log(user.name);

// 实例对象重新赋值
user.name = "微信公众号:储凡";

// 实例对象重载,不会执行save()方法更新数据库
await user.reload();
console.log(user.name); 

注意:reload() 调用生成一个 SELECT 查询,以从数据库中获取最新数据。

保存部分字段

通过传递一个列名数组,可以定义在调用 save() 时应该保存哪些属性。基于先前定义的对象设置属性时, 例如:当你通过 Web 应用程序的形式获取对象的值,这非常有用。

此外,这在 update 实现中内部使用。 它是这样的:

// 创建实例对象
const user = await User.create({
  name: "142vip.cn"
});

// 获取实例属性
console.log(user.name);
// 属性未初始化赋值,则采用默认值
console.log(user.favoriteColor); // "green"

// 实例对象对象重新赋值
user.name = "142vip.cn";
user.favoriteColor = "blue";

// 保存数据,只更新name属性
await user.save({fields: ['name']});

// name属性已更新为Tom
console.log(user.name);

// 显示为 "blue",因为本地对象将其设置为 "blue"
// 在数据库中仍然是 "green",该字段未作更新
console.log(user.favoriteColor); // "blue"

// 实例对象重载后,获取最新的数据库数据
await user.reload();

// 检查到name属性已改为Tom 其他属性未作更改
console.log(user.name);
console.log(user.favoriteColor); // "green"

save()方法说明

save()方法在内部进行了优化,只更新真正更改的字段。

  • 如果不更改任何内容并调用save()方法,Sequelize将知道save()方法是多余的,并且不执行任何操作, 不会生成任何查询。
  • 如果在调用save()方法时只有几个属性发生了更改,那么在UPDATE操作时,将只发送这些更改字段,以提高性能

数据递增或递减

为了递增/递减实例的值而不会遇到并发问题,Sequelize提供了 incrementdecrement 实例方法.

  • increment 递增
  • decrement 递减
// 创建实例对象
const user = await User.create({
  name: "142vip.cn",
  age: 18
});

// age属性+1
await user.increment('age', {
  by: 2
});

注意: 如只增加 1, 你可以省略 by 参数, 只需执行 user.increment('age')方法。

  • PostgreSQL 中, 除非设置了 {returning:false} 参数(不然它将是 undefined), 否则 incrementResult 将是更新后的 user
  • 在其它数据库方言中, incrementResult 将会是 undefined。 如果你需要更新的实例, 你需要调用 user.reload()方法

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

// 创建实例对象
const user = await User.create({
  name: "142vip.cn",
  age: 100
});

// 指定字段
await user.increment({
  age: 2,
});

// 如果值增加相同的数量,则也可以使用以下其他语法:
await user.increment(['age'], {
  by: 2
});

递增、递减的工作原理完全相同。