Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sequelize.js 如何在不禁用约束的情况下修复循环依赖关系?_Sequelize.js - Fatal编程技术网

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或原始查询添加约束(如果尚未存在)

  • 首先将
    constraint:false
    添加到您在字符和项目所有权之间建立的6个关联中
  • 然后将其添加到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
关联吗?我重写了我的答案