Sequelize 中定义字段默认值出现的坑

在 Sequelize 中,我们可以使用 defaultValue 定义数据库中字段的默认值。然而,使用默认值时,有时候我们会遇到一些意想不到的问题,特别是在多线程服务器上面。这篇文章将探讨默认值出现的一些坑,并介绍如何避免它们。

问题背景

假设我们有一个用户模型定义,如下所示:

const User = sequelize.define('user', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  name: {
    type: DataTypes.STRING,
    defaultValue: `user-${Date.now()}`
  },
  age: {
    type: DataTypes.INTEGER,
    defaultValue: 18
  }
})

在这个模型中,我们定义了一个名为 name 的字符串字段和一个名为 age 的整数字段。并且,我们使用 defaultValue 分别为它们定义了默认值。

然而,当我们创建多个用户时,我们会发现它们的名字都是一样的,如下所示:

for (let i = 1; i <= 10; i++) {
  User.create({})
    .then(user => console.log(user.name))
}

输出结果:

这是因为在默认值的定义中我们使用了 JavaScript 表达式,而 Sequelize 在定义模型时只运行一次 JavaScript 表达式,然后将其结果作为默认值。因此,我们的默认值只会被计算一次,从而导致了这个问题。

解决方案

为了避免这个问题,我们需要使用一个函数来定义默认值。这个函数将在每次需要默认值时被调用,从而保证每个实例的默认值都是唯一的。

改进后的模型定义如下:

const User = sequelize.define('user', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  name: {
    type: DataTypes.STRING,
    defaultValue() {
      return `user-${Date.now()}`
    }
  },
  age: {
    type: DataTypes.INTEGER,
    defaultValue: 18
  }
})

现在,我们来创建一个新的用户并输出它的名字:

User.create({})
  .then(user => console.log(user.name))

输出结果:

我们可以看到,现在它的名字是唯一的。

总结

在 Sequelize 中定义默认值时,使用函数定义是避免出现坑的最佳方法。这可以确保每个实例的默认值都是唯一的。

当然,这个问题不仅仅局限于 Sequelize,其他 ORM 也可能会遇到类似的问题。在定义默认值时,一定要小心并考虑到多线程服务器等特殊情况。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a7ef33add4f0e0ff1118ff


纠错反馈