Sequelize Associations
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 */ });
A.hasOne(B)
- 1 대 1
- foreign key는 B에 정의되어있다. 즉, A테이블은 B테이블이 없어도 존재할 수 있지만 B테이블은 A테이블 없이 존재할 수 없다.
A.belongsTo(B)
- foreign key는 A에 정의되어있다. 즉, B테이블은 A테이블이 없어도 존재할 수 있지만 A테이블은 B테이블 없이 존재할 수 없다.
A.hasMany(B)
- 1 대 다
- foreign key는 B에 정의되어있다. 즉, A테이블은 B테이블 없이 존재할 수 있지만 B테이블은 A테이블 없이 존재할 수 없다.
A.belongsToMany(B)
- 다 대 다
- foreign key는 A와 B에 모두 정의되어있다.
- option 객체 필수
- Acotr 테이블과 Movie 테이블이 있다고 할때, 한명의 배우는 여러 영화에 출연할 수 있고, 하나의 영화에는 여러명의 배우들이 참여할 수 있으므로 두 테이블은 다 대 다 관계이다.
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로 연결을 해주어야 하는걸까..
데이터 통합성 (data integrity)
한 테이블에 존재하는 데이터가 다른 테이블에 존재하지 않는 데이터를 참조하는 일이 발생하지 않는다. FK로 설정함으로써, 두 테이블간의 관계를 이해할 수 있다.
Orphan record 방지
FK 관계는 부모-자식 관계로 이해할 수 있는데, 자식은 부모를 참조하고 있다. FK가 없다면, 부모 레코드를 삭제했을때, 관련된 자식 레코드는 존재하지 않는 레코드를 참조하게 된다. FK를 설정하면, 제약조건을 설정할 수 있다. 부모테이블을 참조하는 자식 테이블이 존재할 경우, 부모 테이블/레코드를 삭제하지 못하도록 하거나, 연결된 자식 테이블의 데이터도 삭제시키도록 하는 등 설정할 수 있다.
reference
Author And Source
이 문제에 관하여(Sequelize Associations), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@kaitlin_k/Sequelize-Associations저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)