Sequelize Associations

Creating the dots·2021년 11월 27일
0

project-3-ShallWeHealth

목록 보기
7/26

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

profile
어제보다 나은 오늘을 만드는 중

0개의 댓글