Sequelize.js 如何在不禁用约束的情况下修复循环依赖关系?
我正在为我的游戏开发一个数据库,这就是我如何设计数据库来存储哪个角色拥有哪个项目 模型: 字符型号:Sequelize.js 如何在不禁用约束的情况下修复循环依赖关系?,sequelize.js,Sequelize.js,我正在为我的游戏开发一个数据库,这就是我如何设计数据库来存储哪个角色拥有哪个项目 模型: 字符型号: sequelize.define('characters', { id: { type: DataTypes.STRING, primaryKey: true } primary_slot: { type: DataTypes.INTEGER },
sequelize.define('characters', {
id: {
type: DataTypes.STRING,
primaryKey: true
}
primary_slot: {
type: DataTypes.INTEGER
},
secondary_slot: {
type: DataTypes.INTEGER
},
armor_slot: {
type: DataTypes.INTEGER
}
}, {
freezeTableName: true
});
sequelize.define('items', {
id: {
type: DataTypes.STRING,
primaryKey: true
},
name: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
damage: {
type: DataTypes.INTEGER,
defaultValue: 0
}
}, {
freezeTableName: true,
timestamps: false
});
sequelize.define('item_ownerships', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
owner_id: {
type: DataTypes.STRING
},
item_id: {
type: DataTypes.INTEGER
},
durability: {
type: DataTypes.INTEGER
},
status: {
type: DataTypes.STRING,
allowNull: false
}
}
项目型号:
sequelize.define('characters', {
id: {
type: DataTypes.STRING,
primaryKey: true
}
primary_slot: {
type: DataTypes.INTEGER
},
secondary_slot: {
type: DataTypes.INTEGER
},
armor_slot: {
type: DataTypes.INTEGER
}
}, {
freezeTableName: true
});
sequelize.define('items', {
id: {
type: DataTypes.STRING,
primaryKey: true
},
name: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
damage: {
type: DataTypes.INTEGER,
defaultValue: 0
}
}, {
freezeTableName: true,
timestamps: false
});
sequelize.define('item_ownerships', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
owner_id: {
type: DataTypes.STRING
},
item_id: {
type: DataTypes.INTEGER
},
durability: {
type: DataTypes.INTEGER
},
status: {
type: DataTypes.STRING,
allowNull: false
}
}
字符
和项目
模型之间的关系是通过项目所有权
表的多对多关系:
Characters.belongsToMany(models.items, {
through: 'item_ownerships',
foreignKey: 'owner_id',
otherKey: 'item_id'
});
Items.belongsToMany(models.characters, {
through: 'item_ownerships',
foreignKey: 'item_id',
otherKey: 'owner_id'
});
项目所有权模型:
sequelize.define('characters', {
id: {
type: DataTypes.STRING,
primaryKey: true
}
primary_slot: {
type: DataTypes.INTEGER
},
secondary_slot: {
type: DataTypes.INTEGER
},
armor_slot: {
type: DataTypes.INTEGER
}
}, {
freezeTableName: true
});
sequelize.define('items', {
id: {
type: DataTypes.STRING,
primaryKey: true
},
name: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
damage: {
type: DataTypes.INTEGER,
defaultValue: 0
}
}, {
freezeTableName: true,
timestamps: false
});
sequelize.define('item_ownerships', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
owner_id: {
type: DataTypes.STRING
},
item_id: {
type: DataTypes.INTEGER
},
durability: {
type: DataTypes.INTEGER
},
status: {
type: DataTypes.STRING,
allowNull: false
}
}
如下所示,我在item\u ownerships
表中添加了一个额外的id
列,因为我希望该表中的每个条目都有一个唯一的id作为主键,而不是主键是两个外键owner\u id
和item\u id
的组合键
现在我的问题来了,我想定义以下关联:
Item_ownerships.hasOne(models.characters, {
foreignKey: 'primary_slot'
});
Item_ownerships.hasOne(models.characters, {
foreignKey: 'secondary_slot'
});
Item_ownerships.hasOne(models.characters, {
foreignKey: 'armor_slot'
});
Characters.belongsTo(models.item_ownerships, {
foreignKey: 'primary_slot'
});
Characters.belongsTo(models.item_ownerships, {
foreignKey: 'secondary_slot'
});
Characters.belongsTo(models.item_ownerships, {
foreignKey: 'armor_slot'
});
也就是说,我希望字符的primary\u slot
列保存item\u ownerships
表中项目所有权的ID(foreignKey)。
我得到的错误如下:
Sequelize:找到循环依赖项。依赖链:字符->项目所有权=>字符
添加约束:false
不是这里的操作过程,因为这样我就没有foreignkey约束了。我希望角色只能装备他们在物品所有权
表中拥有的物品
编辑:固定打字错误您应该为同一模型之间的所有关联添加别名,以便Sequelize将它们彼此区分开来:
Items.hasOne(models.md_characters, {
foreignKey: 'primary_slot',
as: 'PrimarySlot'
});
Items.hasOne(models.md_characters, {
foreignKey: 'secondary_slot',
as: 'SecondarySlot'
});
Items.hasOne(models.md_characters, {
foreignKey: 'armor_slot',
as: 'ArmorSlot'
});
MD_characters.belongsTo(models.item_ownerships, {
foreignKey: 'primary_slot',
as: 'PrimaryOwnership'
});
MD_characters.belongsTo(models.item_ownerships, {
foreignKey: 'secondary_slot',
as: 'SecondaryOwnership'
});
MD_characters.belongsTo(models.item_ownerships, {
foreignKey: 'armor_slot',
as: 'ArmorOwnership'
});
根据这里的sequelize文档,sequelize不知道首先创建哪个表,当您使用sequelize.sync()函数自动创建表时,以及当您有循环依赖关系表时,会发生这种情况。
sequelize建议在您的关联中添加
约束:false
,这样sequelize将不会尝试放置外键约束,并且能够创建表而不会产生任何混乱。现在,为了解决您的问题,sequelize创建表后/您自己创建表=>您需要自己创建外键和约束。
或
如果您仍然需要某种自动化,我们有一个解决方法 无论您在哪里使用sequelize.sync(),我们都可以稍后通过使用queryInterface或原始查询添加约束(如果尚未存在)
- 首先将
添加到您在字符和项目所有权之间建立的6个关联中constraint:false
- 然后将其添加到sequelize.sync()中
//使用lodash库迭代对象数组以查找匹配的对象
const=require('lodash');
/**
*续集对象初始化和其他代码
*/
sequelize.sync()
。然后(异步()=>{
// https://sequelize.org/master/manual/query-interface.html
const queryInterface=sequelize.getQueryInterface();
// https://sequelize.org/master/class/lib/dialects/abstract/query-interface.js~QueryInterface.html
const constraints=await queryInterface.getForeignKeyReferencesForTable('characters');
//console.log('constraints',constraints);
/**
*提供以下2种方法在运行时创建约束
*只使用其中一种适合你需要的
*他们俩都做同样的事
*此外,我们还需要首先检查约束是否已经存在
*不存在类似“如果不存在添加约束”的查询
*至少在我使用的博士后中
*/
//检查约束是否不存在
if(!\uu.find(constraint,(constraint)=>constraint.constraintName==='character\u primary\u slot\u item\u owner\u fk')){
log(“添加约束”);
//方法1-使用直接原始查询
const query_p=`ALTER TABLE“characters”ADD CONSTRAINT“character\u primary\u slot\u item\u owner\u fk”外键(“primary\u slot”)引用“item\u ownerships”(“id”)`
等待sequelize.query(query\p);
//方法2-使用查询接口函数
等待queryInterface.addConstraint('字符'{
键入:“外键”,
字段:['primary_slot'],
名称:'character\u primary\u slot\u item\u owner\u fk',
参考资料:{
表:“项目所有权”,
字段:“id”,
}
});
}
/**
*对其他两列重复“如果”部分
*或者做一个函数来做这个
*/
log('DB synced');
})
.catch((错误)=>{
console.log('error',err);
});
我在帖子上打错了字。在代码中,我使用了Items.hasOne
而不是Items.hasOne
来代替Items.hasOne
来代替Items.hasOne
没有意义,因为它们的主键与primary\u slot
列没有任何关系。MD\u字符也是如此(models.item_ownerships
你怎么说它们根本不相关?来自item_ownerships
的主键应该是MD_字符
中的外键(或者更确切地说是字符
)表.primary\u slot
、secondary\u slot
和armor
列引用了item\u ownerships
中的PK。至少,这是我试图实现的目标。你能在帖子中添加manytomy
关联吗?我重写了我的答案