associations 유형
associations의 유형은 다음과 같이 네 가지로 나뉜다. 아래와 같이 작성하면 자동으로 해당 모델에 foreign key가 생성된다.
//여기서 A는 source, B는 target이라고 한다.
//belongsToMany만 option 객체가 필수이다.
A.hasOne(B, { /* options */ });
A.belongsTo(B, { /* options */ });
A.hasMany(B, { /* options */ });
A.belongsToMany(B, { through: 'C', /* options */ });
associations 적용
공부한 내용을 토대로 쉘위헬스 Model에 association을 추가했고, migrations 파일에 references를 추가했다.
//models/users.js
static associate(models) {
// define association here
Users.hasMany(Posts, {
foreignKey: {
name: 'giverId',
name: 'receiverId'
},
onDelete: 'SET NULL' //default 설정임
});
Users.hasMany(Issues, {
foreignKey: {
name: 'reporterId',
name: 'targetId'
},
onDelete: 'SET NULL'
});
Users.hasMany(Chats, {
foreignKey: {
name: 'authorId'
},
onDelete: 'SET NULL'
});
Users.hasMany(Thumbsups, {
foreignKey: {
name: 'giverId',
name: 'receiverId'
},
onDelete: 'CASCADE'
});
};
//models/posts.js
static associate(models) {
// define association here
Posts.belongsTo(Users, {
onDelete: 'SET NULL'
});
Posts.hasMany(Issues, {
foreignKey: {
name: 'postId'
},
onDelete: 'SET NULL'
});
Posts.hasOne(Chats, {
foreignKey: {
name: 'roomId',
},
onDelete: 'SET NULL'
});
Posts.hasMany(Thumbsups, {
foreignKey: {
name: 'postId'
},
onDelete: 'SET NULL'
});
};
//models/issues.js
static associate(models) {
// define association here
Issues.belongsTo(Posts, {
onDelete: 'SET NULL'
});
Issues.belongsTo(Users, {
onDelete: 'SET NULL'
});
};
//models/chats.js
static associate(models) {
// define association here
Chats.belongsTo(Users, {
onDelete: 'SET NULL'
});
Chats.belongsTo(Posts, {
onDelete: 'SET NULL'
});
};
//models/thumbsup.js
static associate(models) {
// define association here
Thumbsups.belongsTo(Posts, {
onDelete: 'SET NULL'
});
Thumbsups.belongsTo(Users, {
onDelete: 'CASCADE'
});
};
//FK를 갖는 테이블에 아래와 같이 references를 다음과 같이 추가함.
//모든 파일에 비슷한 형태로 적용되므로 예시는 issue만 작성.
migrations/issue
postId: {
type: Sequelize.INTEGER,
references: {
model: "Posts",
key: "id",
as: "postId",
},
},
reporterId: {
type: Sequelize.INTEGER,
references: {
model: "Users",
key: "id",
as: "reporterId",
},
},
targetId: {
type: Sequelize.INTEGER,
references: {
model: "Users",
key: "id",
as: "targetId",
},
},
다음과 같이 데이터베이스가 수정된 것을 확인할 수 있다.
왜 FK를 쓰는걸까?
associations를 작성하면서, 문득 왜 이렇게 많은 fk를 써야하는지 궁금해졌다. users 테이블의 id를 왜 이렇게 거의 모든 테이블에 fk로 연결을 해주어야 하는걸까..
한 테이블에 존재하는 데이터가 다른 테이블에 존재하지 않는 데이터를 참조하는 일이 발생하지 않는다. FK로 설정함으로써, 두 테이블간의 관계를 이해할 수 있다.
FK 관계는 부모-자식 관계로 이해할 수 있는데, 자식은 부모를 참조하고 있다. FK가 없다면, 부모 레코드를 삭제했을때, 관련된 자식 레코드는 존재하지 않는 레코드를 참조하게 된다. FK를 설정하면, 제약조건을 설정할 수 있다. 부모테이블을 참조하는 자식 테이블이 존재할 경우, 부모 테이블/레코드를 삭제하지 못하도록 하거나, 연결된 자식 테이블의 데이터도 삭제시키도록 하는 등 설정할 수 있다.
reference