在 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)) }
输出结果:
user-1618302121478 user-1618302121478 user-1618302121478 user-1618302121478 user-1618302121478 user-1618302121478 user-1618302121478 user-1618302121478 user-1618302121478 user-1618302121478
这是因为在默认值的定义中我们使用了 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))
输出结果:
user-1618302121478
我们可以看到,现在它的名字是唯一的。
总结
在 Sequelize 中定义默认值时,使用函数定义是避免出现坑的最佳方法。这可以确保每个实例的默认值都是唯一的。
当然,这个问题不仅仅局限于 Sequelize,其他 ORM 也可能会遇到类似的问题。在定义默认值时,一定要小心并考虑到多线程服务器等特殊情况。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a7ef33add4f0e0ff1118ff