问题描述
我要实现的目标是:添加新的竞赛时,我需要在表 team_comp 中创建一行,其中包含表竞争以及我根据要求发送的其他数据。我将参加很多比赛,但每个比赛都有一个属于它的team_comp。如果我删除比赛,则必须删除其team_comp行。
表格竞争:
| id | name | competition_teams |
| 1 | A | 32 |
表 team_comp :
| id | competition_id | test_h |
| 3 | 32 | 1 |
在我的 models / index.js 中,我正在定义如下关联:
// Competition
db.competition.hasOne(db.competition_team,{as: 'compId',foreignKey : 'competition_id'});
// Competition Teams
db.competition_team.belongsTo(db.competition,{as: 'compTeam',foreignKey : 'competition_id',onDelete: 'CASCADE'});
这样做,我得到了错误的外键。它在表** team_comp **中创建一个指向 competion.id 的外键,而不指向 competition.competition_teams 的外键(这是我想要的)。 如何让它指向Competition.competition_teams?
这是我添加新竞赛(控制器/ Competition.js)的方式:
import db from '../models/index';
const Competition = db.competition;
const Competition_teams = db.competition_team;
// create competition
const create = (req,res) => {
// generating a random id for the competition
var competition_teams = Math.floor(Math.random() * 100);
let {
name,test_h,} = req.body;
// create new Competition
let newCompetition = {
name,competition_teams // this must be also added in table team_comp,column competition_id
}
let newCompetitionTeams = {
test_h
}
Competition.create(newCompetition)
.then(Competition => {
res.json({ Competition });
})
.catch(err => {
console.log("Error: " + err);
return res.status(500).json({ err });
});
// creating teams association
Competition_teams.create(newCompetitionTeams)
.then(Competition_teams => {
res.json({ Competition_teams });
})
.catch(err => {
console.log("Error: " + err);
return res.status(500).json({ err });
});
}
解决方法
您需要在关联中指定sourceKey
属性-如果被忽略,它将使用table + id Reference
用作源表中关联的键的属性名称。默认为源表的主键
请参见以下完整示例:
class Competition extends Sequelize.Model {
}
Competition.init({
id: {
primaryKey: true,type: Sequelize.INTEGER,allowNull: false
},name: {
type: Sequelize.STRING(36)
},team_competition_id: {
type: Sequelize.INTEGER,allowNull: false,}
},{
sequelize,modelName: 'competition',tableName: 'competitions',timestamps: false
});
class Team_Competition extends Sequelize.Model {
}
Team_Competition.init({
id: {
primaryKey: true,},modelName: 'team_competition',tableName: 'team_competitions',timestamps: false
});
// use sourceKey here - also make sure you specify `cascade` and `hooks` property
Competition.hasOne(Team_Competition,{sourceKey: 'team_competition_id',foreignKey: 'id',onDelete: 'cascade',hooks: true});
// tests
// create the team_competition
const team_competition = await Team_Competition.create({
id: 1,name: 'Team A'
});
// create the competition
const competition = await Competition.create({
id: 1,name: 'Comp A',team_competition_id: team_competition.id
});
// test the join
const competitions = await Competition.findAll({
include: [
{
attributes: ['id','name'],model: Team_Competition,}
],raw: true
});
// delete and verify cascade
await competition.destroy();
将生成并执行以下SQL:
Executing (default): INSERT INTO "team_competitions" ("id","name") VALUES ($1,$2) RETURNING *;
Executing (default): INSERT INTO "competitions" ("id","name","team_competition_id") VALUES ($1,$2,$3) RETURNING *;
// query
Executing (default): SELECT "competition"."id","competition"."name","competition"."team_competition_id","team_competition"."id" AS "team_competition.id","team_competition"."name" AS "team_competition.name" FROM "competitions" AS "competition" LEFT OUTER JOIN "team_competitions" AS "team_competition" ON "competition"."team_competition_id" = "team_competition"."id";
// cascade deletes
Executing (default): DELETE FROM "team_competitions" WHERE "id" = 1
Executing (default): DELETE FROM "competitions" WHERE "id" = 1