【问题标题】:How to add associations to Models generated from Sequelize-Auto如何向 Sequelize-Auto 生成的模型添加关联
【发布时间】:2019-08-18 04:47:22
【问题描述】:

对于现有的 MySQL 数据库,我使用 Sequelize-auto 包来生成模型。但是模型类没有关联。

我有一个 MySQL 数据库,我将它用于 NodeJS Web 项目。我也使用 Sequelize 作为 ORM。由于数据库已经存在,我想将模型类生成为实体。所以我用了sequelize-auto

https://github.com/sequelize/sequelize-auto 生成模型类。但是,当它们生成时,属性已正确设置,但关联并没有与模型类一起出现。所以我在从数据库中获取数据时遇到了问题。

这是使用 sequlize-auto 生成的两个模型类。数据库中有两个表,分别命名为部门和类别。 department.js 和 category.js 是生成的两个模型类

department.js

module.exports = function(sequelize, DataTypes) {
  return sequelize.define('department', {
        department_id: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: DataTypes.STRING(100),
            allowNull: false
        },
        description: {
            type: DataTypes.STRING(1000),
            allowNull: true
        }
    }, {
        tableName: 'department',
        timestamps: false,
    });
};

category.js

module.exports = function(sequelize, DataTypes) {
  return sequelize.define('category', {
        category_id: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            primaryKey: true,
            autoIncrement: true
        },
        department_id: {
            type: DataTypes.INTEGER(11),
            allowNull: false
        },
        name: {
            type: DataTypes.STRING(100),
            allowNull: false
        },
        description: {
            type: DataTypes.STRING(1000),
            allowNull: true
        }
    }, {
        tableName: 'category',
        timestamps: false,
    });
};

那么还需要做什么才能获得关联并成功获取数据。有人可以在这里帮助我。表结构如下。

【问题讨论】:

标签: mysql node.js orm model sequelize.js


【解决方案1】:

1) 在您的模型文件夹中创建一个 index.js 文件并添加以下代码

import Sequelize from 'sequelize';

const fs = require('fs');
const path = require('path');

const basename = path.basename(__filename);

const db = {};

// @ts-ignore
const sequelize = new Sequelize('dbname', 'dbUser', 'password', {
  host: '127.0.0.1',
  port: 'PORT',
  dialect: 'mysql',
  define: {
    freezeTableName: true,
    timestamps: false,
  },
  pool: {
    max: 5,
    min: 0,
    acquire: 30000,
    idle: 10000,
  },
  // <http://docs.sequelizejs.com/manual/tutorial/querying.html#operators>
  operatorsAliases: false,
});

const tableModel = {};

fs.readdirSync(__dirname)
  .filter(file => file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js')
  .forEach(file => {
    const model = sequelize.import(path.join(__dirname, file));
    db[model.name] = model;
    tableModel[model.name] = model;
  });

Object.getOwnPropertyNames(db).forEach(modelName => {
  const currentModel = db[modelName];
  Object.getOwnPropertyNames(currentModel.rawAttributes).forEach(attributeName => {
    if (
      Object.prototype.hasOwnProperty.call(
        currentModel.rawAttributes[attributeName],
        'references'
      ) &&
      Object.prototype.hasOwnProperty.call(
        currentModel.rawAttributes[attributeName].references,
        'model'
      ) &&
      Object.prototype.hasOwnProperty.call(
        currentModel.rawAttributes[attributeName].references,
        'key'
      )
    ) {
      if (
        !(
          currentModel.rawAttributes[attributeName].references.model &&
          currentModel.rawAttributes[attributeName].references.key
        )
      ) {
        console.log(
          `*SKIPPED* ${modelName} ${attributeName} references a model ${currentModel.rawAttributes[attributeName].references.model} with key ${currentModel.rawAttributes[attributeName].references.key}`
        );
        return;
      }

      console.log(
        `${modelName} ${attributeName} references a model ${currentModel.rawAttributes[attributeName].references.model} with key ${currentModel.rawAttributes[attributeName].references.key}`
      );
      const referencedTable =
        tableModel[currentModel.rawAttributes[attributeName].references.model];

      currentModel.belongsTo(referencedTable, { foreignKey: attributeName });
      referencedTable.hasMany(currentModel, { foreignKey: attributeName });

    }
  });
});

// @ts-ignore
db.sequelize = sequelize;
// @ts-ignore
db.Sequelize = Sequelize;

// eslint-disable-next-line eol-last
module.exports = db;

2) 在您的解析器内部只需参考上述内容:

const db = require('../assets/models/index');

【讨论】:

    【解决方案2】:

    添加到他基于here 的@CodingLittles 答案。

    我添加了以下内容以进行多对多关联:

    enum Junctions {
      user = 'user',
      roles = 'roles',
    }
    
    enum JuntiontThrough {
      userroles = 'userroles',
    }
    
    
    interface JunctionObject {
      junctionBelongsTo?: any;
    }
    
    const checkIfAttrExists= (obj, value) => {
      return Object.prototype.hasOwnProperty.call(obj, value);
    };
    
    const checkRefrence = (obj, attr, value) => {
      return obj.rawAttributes[attr].references[value];
    };
    
    
    export const getJunction = (junc: Junctions): JunctionObject => {
      const junctions = {
        user: {
          junctionBelongsTo: [
            { key: Junctions.roles, value: juntiontThrough.userroles }
          ],
        },
        roles: {
          junctionBelongsTo: [{ key: Junctions.user, value: juntiontThrough.userroles }],
        },
      }[junc];
    
      if (!junctions) return {};
    
      return junctions;
    };
    
    
      const models = Object.getOwnPropertyNames(db);
    
    models.forEach(modelName => {
      const currentModel = db[modelName];
      const junction = getJunction(modelName as Junctions);
    
      if (!_.isEmpty(junction)) {
        // eslint-disable-next-line array-callback-return
        junction.junctionBelongsTo.reduce((key, value) => {
          currentModel.belongsToMany(db[value.key], {
            through: db[value.value],
          });
        }, {});
      }
    
      const attributes = Object.getOwnPropertyNames(currentModel.rawAttributes);
    
      attributes.forEach(attributeName => {
        if (
          checkIfAttrExists(currentModel.rawAttributes[attributeName], 'references') &&
          checkIfAttrExists(currentModel.rawAttributes[attributeName].references, 'model') &&
          checkIfAttrExists(currentModel.rawAttributes[attributeName].references, 'key')
        ) {
          if (
            !(
              checkRefrence(currentModel, attributeName, 'model') &&
              checkRefrence(currentModel, attributeName, 'key')
            )
          ) {
            return;
          }
    
          const referencedTable =
            tableModel[currentModel.rawAttributes[attributeName].references.model];
    
          if (!(modelName.toString() in juntiontThrough)) {
            console.log(
              `${modelName} ${attributeName} references a model ${currentModel.rawAttributes[attributeName].references.model} with key ${currentModel.rawAttributes[attributeName].references.key}`
            );
            currentModel.belongsTo(referencedTable, { foreignKey: attributeName });
            referencedTable.hasMany(currentModel, { foreignKey: attributeName });
          }
        }
      });
    })
    

    请注意,要使多对多关系起作用,您必须像我在 getJunction 函数中所做的那样手动添加关系

    【讨论】:

      【解决方案3】:

      我遵循sequelize-auto (init-models.ts) 上的打字稿示例中演示的模式 - 在现有的 initModels 函数中,在 js 中可以正常工作。

      export function initModels(sequelize: Sequelize) {
        Product.initModel(sequelize);
        Supplier.initModel(sequelize);
        
        Supplier.hasMany(Product, { as: "products", foreignKey: "supplierId"});
        
        return {...

      【讨论】:

        猜你喜欢
        • 2021-08-02
        • 2021-03-20
        • 2019-08-18
        • 1970-01-01
        • 2018-12-09
        • 2020-08-05
        • 2017-03-30
        • 1970-01-01
        • 2014-10-24
        相关资源
        最近更新 更多