Sequelize定义多对多关联时出现循环依赖错误排查
Sequelize多对多关联同步报错:模型类型不匹配
尝试在BlogPost和Category模型间定义多对多关联,按官方文档完成模型定义后,调用sequelize.sync()时出现以下错误:
/Users/muoki/Sites/node_blog/node_modules/sequelize/lib/associations/mixin.js:33 throw new Error(`${this.name}.belongsToMany called with something that's not a subclass of Sequelize.Model`); ^ Error: category.belongsToMany called with something that's not a subclass of Sequelize.Model at Function.belongsToMany (/Users/muoki/Sites/node_blog/node_modules/sequelize/lib/associations/mixin.js:33:13) at Object.<anonymous> (/Users/muoki/Sites/node_blog/models/Category.js:20:10) at Module._compile (node:internal/modules/cjs/loader:1105:14) at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10) at Module.load (node:internal/modules/cjs/loader:981:32) at Function.Module._load (node:internal/modules/cjs/loader:822:12) at Module.require (node:internal/modules/cjs/loader:1005:19) at require (node:internal/modules/cjs/helpers:102:18) at Object.<anonymous> (/Users/muoki/Sites/node_blog/models/BlogPost.js:4:18) at Module._compile (node:internal/modules/cjs/loader:1105:14) [nodemon] app crashed - waiting for file changes before starting...
移除任意一方的关联配置后,数据库同步成功,中间表blog_category也能正常创建。
现有模型代码
BlogPost.js
const Sequelize = require("sequelize"); const sequelize = require("../util/database"); const User = require("./User"); const Category = require("./Category"); const BlogPost = sequelize.define( "blog_post", { id: { primaryKey: true, autoIncrement: true, type: Sequelize.DataTypes.BIGINT, }, image_url: { type: Sequelize.DataTypes.TEXT, }, title: { type: Sequelize.DataTypes.STRING, allowNull: false, }, content: { type: Sequelize.DataTypes.TEXT, allowNull: false, }, }, { timestamps: true, createdAt: "created_at", updatedAt: "updated_at", } ); BlogPost.belongsTo(User); BlogPost.belongsToMany(Category, { through: "blog_category", }); module.exports = BlogPost;
Category.js
const Sequelize = require("sequelize"); const sequelize = require("../util/database"); const BlogPost = require("./BlogPost"); const Category = sequelize.define("category", { id: { type: Sequelize.DataTypes.BIGINT, notNull: true, primaryKey: true, autoIncrement: true, }, category: { type: Sequelize.DataTypes.STRING, notNull: true, }, }); Category.belongsToMany(BlogPost, { through: "blog_category", }); module.exports = Category;
问题原因及解决办法
原因
两个模型文件互相require对方,触发了循环依赖:加载BlogPost.js时会去加载Category.js,而加载Category.js又会回头加载BlogPost.js,此时其中一个模型还未完成sequelize.define的执行,导致传递给belongsToMany的不是完整的Sequelize.Model子类,从而抛出错误。
解决办法:统一管理模型关联
最稳妥的方式是创建一个模型入口文件(比如models/index.js),在所有模型都加载完成后再定义关联,避免循环依赖。
修改模型文件,移除内部关联代码
- 更新
BlogPost.js,删除const Category = require("./Category")和BlogPost.belongsToMany(...):const Sequelize = require("sequelize"); const sequelize = require("../util/database"); const User = require("./User"); const BlogPost = sequelize.define( "blog_post", { id: { primaryKey: true, autoIncrement: true, type: Sequelize.DataTypes.BIGINT, }, image_url: { type: Sequelize.DataTypes.TEXT, }, title: { type: Sequelize.DataTypes.STRING, allowNull: false, }, content: { type: Sequelize.DataTypes.TEXT, allowNull: false, }, }, { timestamps: true, createdAt: "created_at", updatedAt: "updated_at", } ); BlogPost.belongsTo(User); module.exports = BlogPost; - 更新
Category.js,删除const BlogPost = require("./BlogPost")和Category.belongsToMany(...):const Sequelize = require("sequelize"); const sequelize = require("../util/database"); const Category = sequelize.define("category", { id: { type: Sequelize.DataTypes.BIGINT, notNull: true, primaryKey: true, autoIncrement: true, }, category: { type: Sequelize.DataTypes.STRING, notNull: true, }, }); module.exports = Category;
- 更新
创建
models/index.js,统一加载模型并定义关联const sequelize = require("../util/database"); const BlogPost = require("./BlogPost"); const Category = require("./Category"); const User = require("./User"); // 定义多对多关联 BlogPost.belongsToMany(Category, { through: "blog_category" }); Category.belongsToMany(BlogPost, { through: "blog_category" }); module.exports = { sequelize, BlogPost, Category, User };在项目入口文件中,引入
models/index.js而非单独模型
比如在启动文件中:const { sequelize } = require("./models/index"); // 同步数据库 sequelize.sync() .then(() => console.log("数据库同步成功")) .catch(err => console.error("同步失败:", err));
这样就能避免循环依赖问题,正常建立多对多关联并同步数据库。
内容的提问来源于stack exchange,提问作者muoki_D
相关产品推荐
相关产品推荐

