NodeJS EagerLoadingError [SequelizeEagerLoadingError]:攻击与角色无关

7y4bm7vi  于 2023-10-17  发布在  Node.js
关注(0)|答案(1)|浏览(71)

我尝试将8个模型与1个模型关联,但每次我尝试使用“include”查询主模型时,都会得到相同的消息
EagerLoadingError [SequelizeEagerLoadingError]:攻击与角色无关!
通过PgAdmin查看数据库,它说所有8个表都与主表相关联,如果我试图删除主表,则会弹出警告,说另一个表依赖于此表。我的文件是:

角色模型(主模型)

import Sequelize, { Model } from 'sequelize';
import bcryptjs from 'bcryptjs';

export default class Character extends Model {
  static init(sequelize) {
    super.init({
      character: {
        type: Sequelize.STRING,
        defaultValue: '',
        validate: {
          notEmpty: {
            msg: 'Informe o nome do personagem',
          },
        },
      },
      player: {
        type: Sequelize.STRING,
        defaultValue: '',
        validate: {
          notEmpty: {
            msg: 'Informe o nome do jogador',
          },
        },
      },
      password: {
        type: Sequelize.VIRTUAL,
        defaultValue: '',
        validate: {
          len: {
            args: [6, 18],
            msg: 'A senha deve ter de 6 a 18 caracteres',
          },
        },
      },
      password_hash: {
        type: Sequelize.STRING,
        defaultValue: '',
      },
      origin: {
        type: Sequelize.STRING,
        defaultValue: '',
      },
      class: {
        type: Sequelize.STRING,
        defaultValue: '',
      },
      level: {
        type: Sequelize.INTEGER,
        defaultValue: 0,
      },
      movement: {
        type: Sequelize.INTEGER,
        defaultValue: 0,
      },
      max_pv: {
        type: Sequelize.INTEGER,
        defaultValue: 0,
      },
      current_pv: {
        type: Sequelize.INTEGER,
        defaultValue: 0,
      },
      max_san: {
        type: Sequelize.INTEGER,
        defaultValue: 0,
      },
      current_san: {
        type: Sequelize.INTEGER,
        defaultValue: 0,
      },
      defense: {
        type: Sequelize.INTEGER,
        defaultValue: 0,
      },
      equipments: {
        type: Sequelize.INTEGER,
        defaultValue: 0,
      },
      others: {
        type: Sequelize.INTEGER,
        defaultValue: 0,
      },
      protection: {
        type: Sequelize.STRING,
        defaultValue: '',
      },
      resistence: {
        type: Sequelize.TEXT,
        defaultValue: '',
      },
    }, {
      sequelize,
    });

    this.addHook('beforeSave', async (char) => {
      char.password_hash = await bcryptjs.hash(char.password_hash, 8);
    });

    return this;
  }

  static associate(models) {
    this.hasMany(models.Attack, { foreignKey: 'character_id' });
    this.hasMany(models.Ability, { foreignKey: 'character_id' });
    this.hasMany(models.Item, { foreignKey: 'character_id' });
    this.hasMany(models.Strength, { foreignKey: 'character_id' });
    this.hasMany(models.Presence, { foreignKey: 'character_id' });
    this.hasMany(models.Intelect, { foreignKey: 'character_id' });
    this.hasMany(models.Vigor, { foreignKey: 'character_id' });
    this.hasMany(models.Agility, { foreignKey: 'character_id' });
  }
}

攻击模型(关联模型之一)

import Sequelize, { Model } from 'sequelize';

export default class Attack extends Model {
  static init(sequelize) {
    super.init({
      name: {
        type: Sequelize.STRING,
        defaultValue: '',
      },
      test: {
        type: Sequelize.STRING,
        defaultValue: '',
      },
      damage: {
        type: Sequelize.STRING,
        defaultValue: '',
      },
      others: {
        type: Sequelize.STRING,
        defaultValue: '',
      },
    }, {
      sequelize,
      tableName: 'attacks',
    });
    return this;
  }

  static associate(models) {
    this.belongsTo(models.Character, { foreignKey: 'character_id' });
  }
}

攻击表迁移

/** @type {import('sequelize-cli').Migration} */
module.exports = {
  up: (queryInterface, Sequelize) => queryInterface.createTable('attacks', {
    id: {
      type: Sequelize.INTEGER,
      allowNull: false,
      autoIncrement: true,
      primaryKey: true,
    },
    name: {
      type: Sequelize.STRING,
      allowNull: true,
    },
    test: {
      type: Sequelize.STRING,
      allowNull: true,
    },
    damage: {
      type: Sequelize.STRING,
      allowNull: true,
    },
    others: {
      type: Sequelize.STRING,
      allowNull: true,
    },
    character_id: {
      type: Sequelize.INTEGER,
      allowNull: true,
      references: {
        model: 'Character',
        // already tried to put the table name instead of the model name doesn't work either
        key: 'id',
      },
    },
    created_at: {
      type: Sequelize.DATE,
    },
    updated_at: {
      type: Sequelize.DATE,
    },
  }),

  down: (queryInterface) => queryInterface.dropTable('attacks'),
};

字符表迁移

/** @type {import('sequelize-cli').Migration} */
module.exports = {
  up: (queryInterface, Sequelize) => queryInterface.createTable('characters', {
    id: {
      type: Sequelize.INTEGER,
      allowNull: false,
      autoIncrement: true,
      primaryKey: true,
    },
    character: {
      type: Sequelize.STRING,
      allowNull: true,
    },
    player: {
      type: Sequelize.STRING,
      allowNull: true,
    },
    password_hash: {
      type: Sequelize.STRING,
      allowNull: true,
    },
    origin: {
      type: Sequelize.STRING,
      allowNull: true,
    },
    class: {
      type: Sequelize.STRING,
      allowNull: true,
    },
    level: {
      type: Sequelize.INTEGER,
      allowNull: true,
    },
    movement: {
      type: Sequelize.INTEGER,
      allowNull: true,
    },
    max_pv: {
      type: Sequelize.INTEGER,
      allowNull: true,
    },
    current_pv: {
      type: Sequelize.INTEGER,
      allowNull: true,
    },
    max_san: {
      type: Sequelize.INTEGER,
      allowNull: true,
    },
    current_san: {
      type: Sequelize.INTEGER,
      allowNull: true,
    },
    defense: {
      type: Sequelize.INTEGER,
      allowNull: true,
    },
    equipments: {
      type: Sequelize.INTEGER,
      allowNull: true,
    },
    others: {
      type: Sequelize.INTEGER,
      allowNull: true,
    },
    protection: {
      type: Sequelize.STRING,
      allowNull: true,
    },
    resistence: {
      type: Sequelize.TEXT,
      allowNull: true,
    },
    created_at: {
      type: Sequelize.DATE,
    },
    updated_at: {
      type: Sequelize.DATE,
    },
  }),

  down: (queryInterface) => queryInterface.dropTable('characters'),
};

数据库索引文件

import Sequelize from 'sequelize';
import databaseConfig from '../config/database';
import Character from '../models/Character';
import Ability from '../models/Ability';
import Attack from '../models/Attack';
import Item from '../models/Item';
import Strength from '../models/Attributes/Strength';
import Intelect from '../models/Attributes/Intelect';
import Presence from '../models/Attributes/Presence';
import Vigor from '../models/Attributes/Vigor';
import Agility from '../models/Attributes/Agility';

const models = [Character, Ability, Attack, Item, Strength, Intelect, Presence, Vigor, Agility];

const connection = new Sequelize(databaseConfig);

models.forEach((model) => model.init(connection));

我执行查询的操作器控制器

import Character from '../models/Character';
// import Ability from '../models/Ability';
import Attack from '../models/Attack';
// import Item from '../models/Item';
// import Strength from '../models/Attributes/Strength';
// import Intelect from '../models/Attributes/Intelect';
// import Presence from '../models/Attributes/Presence';
// import Vigor from '../models/Attributes/Vigor';
// import Agility from '../models/Attributes/Agility';

class CharacterController {
  async index(req, res) {
    const characters = await Character.findAll({
      order: [['id', 'DESC'], [Attack, 'id', 'DESC']],
      include: {
        model: Attack,
      },
    });
    return res.status(200).json(characters);
  }

  async store(req, res) {
    try {
      const newCharacter = await Character.create(req.body);
      return res.status(200).json(newCharacter);
    } catch (e) {
      if (e.errors) {
        return res.status(400).json({
          errors: e.errors.map((err) => err.message),
        });
      }
      return console.log(e);
    }
  }
}

export default new CharacterController();

package.json

{
  "name": "omega-back",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "nodemon server.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "bcryptjs": "^2.4.3",
    "dotenv": "^16.3.1",
    "express": "^4.18.2",
    "jsonwebtoken": "^9.0.2",
    "nodemon": "^3.0.1",
    "pg": "^8.11.3",
    "pg-hstore": "^2.3.4",
    "sequelize": "^6.33.0",
    "sequelize-cli": "^6.6.1",
    "sucrase": "^3.34.0"
  },
  "devDependencies": {
    "eslint": "^8.51.0",
    "eslint-config-airbnb-base": "^15.0.0",
    "eslint-plugin-import": "^2.28.1"
  }
}

我已经尝试过使用“as”进行查询,也把这个“as”放在了BullsTo和hasMany关联中。我寻找的所有解决方案,都没有帮助。有人能试着解决这个问题吗?这样我就能知道问题是出在代码上还是出在屏幕和椅子之间?

scyqe7ek

scyqe7ek1#

看起来你没有通过为每个模型调用associate方法来初始化关联:

models.forEach((model) => model.init(connection));
models.forEach((model) => model.associate(models));

Sequelize对associate方法一无所知,在调用init方法时也不会调用它。

相关问题