node.js - 如何子类化 Model 并正确添加静态方法?
问题描述
我正在学习如何使用 Sequelize 作为小型 Web 应用程序的 ORM。(MySQL) 数据库中的每条记录都有一个uuid
字段。我想为findByUuid
所有模型添加一个静态方法。这是我的尝试:
class Base extends Model {
static findByUuid = async (uuid) => {
return await super.findOne({ where: {uuid: uuid} });
}
}
class List extends Base {
}
List.init({
uuid: {
type: DataTypes.UUID,
allowNull: false,
defaultValue: Sequelize.UUIDV4
},
name: {
type: DataTypes.STRING,
allowNull: false
}
}, {
sequelize,
nodelName: 'List',
indexes: [
{ fields: ['name'] },
{ fields: ['uuid'] }
]
});
(async () => {
await sequelize.sync({ force: true });
const list = List.build({name: 'New List'});
await list.save();
console.log('id: ' + list.id);
console.log('uuid: ' + list.uuid);
const direct_retrieved = await List.findOne({ where: {uuid: list.uuid} });
console.log('direct name: ' + direct_retrieved.name);
const retrieved = await List.findByUuid(list.uuid);
console.log('static retrieved: ' + retrieved.name);
})();
这是输出(不包括回显的 SQL 命令):
id: 1
uuid: 371971dd-a4d9-43aa-ac10-afe3c10154b0
direct name: New List
/Users/chuck/Projects/app/node_modules/sequelize/lib/model.js:1692
this.warnOnInvalidOptions(options, Object.keys(this.rawAttributes));
^
TypeError: Cannot convert undefined or null to object
at Function.keys (<anonymous>)
at Function.findAll (/Users/chuck/Projects/app/node_modules/sequelize/lib/model.js:1692:47)
at Function.findOne (/Users/chuck/Projects/app/node_modules/sequelize/lib/model.js:1917:23)
at Function.findByUuid (/Users/chuck/Projects/app/models/models.js:7:36)
at /Users/chuck/Projects/app/models/models.js:181:34
at processTicksAndRejections (node:internal/process/task_queues:93:5)
所以直接使用findOne
是有效的,但尝试在静态方法中这样做会导致错误,我无法弄清楚原因。
我认为问题在于该Base
班级不了解某个uuid
领域。如果我将静态方法放入List
类中,它可以正常工作。因此,到目前为止,我唯一的解决方案是为每个实际表重复该代码,因为我(还)没有看到uuid
在类中定义字段的方法Base
(无论如何这将是更可取的。
解决方案
事实证明,我需要重写init
以Base
了解该uuid
字段。这是有效的解决方案。
const { Sequelize, DataTypes, Model } = require('sequelize');
const sequelize = require('./helpers/sequelize');
class Base extends Model {
static findByUuid = async (uuid) => {
return await super.findOne({ where: {uuid: uuid} });
}
static init = (attributes, options = {}) => {
attributes.uuid = {
type: DataTypes.UUID,
allowNull: false,
defaultValue: Sequelize.UUIDV4
};
options.indexes.push({ fields: ['uuid'] });
super.init(attributes, options);
}
}
class List extends Base {
}
List.init({
name: {
type: DataTypes.STRING,
allowNull: false
}
}, {
sequelize,
modelName: 'List',
indexes: [
{ fields: ['name'] }
]
});
(async () => {
await sequelize.sync({ force: true });
const list = List.build({name: 'New List'});
await list.save();
console.log('id: ' + list.id);
console.log('uuid: ' + list.uuid);
const direct_retrieved = await List.findOne({ where: {uuid: list.uuid} });
console.log('direct: ' + direct_retrieved.name);
const retrieved = await List.findByUuid(list.uuid);
console.log('static: ' + retrieved.name);
})();
推荐阅读
- reactjs - 大量自定义 Material UI DataTable (React)
- python - 调用函数与内联代码时的不同行为
- python - 无法正确安装 setup.py 以进行人脸识别
- javascript - Vuex:突变中的均方括号是什么?
- git - git-log 缺少取消更改的合并提交
- python - 用最大值打印numpy数组的索引
- python - 如果当天是工作日,则获取当前日期,否则获取最近工作日的日期(即星期五)
- javascript - 如何在 Knex.js 迁移中使用“金钱”数据类型?
- c# - 我有一个关于 ldap 获取 memberOf 值的问题
- javascript - 不要在浏览器或标签关闭时销毁 Vue-Cookie