【问题标题】:How can I subclass Model and properly add a static method?如何子类化 Model 并正确添加静态方法?
【发布时间】:2021-03-08 19:00:09
【问题描述】:

我正在学习如何将 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 类中,它可以正常工作。所以到目前为止我唯一的解决方案是为每个实际表重复该代码,因为我(还)没有看到在Base 类中定义uuid 字段的方法(无论如何这将是更可取的。

【问题讨论】:

    标签: node.js async-await sequelize.js


    【解决方案1】:

    事实证明,我需要覆盖 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);
    })();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-21
      • 1970-01-01
      • 1970-01-01
      • 2017-01-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多