[TIL_2023.11.14] Node.js -Sequelize Associate

김효진·2023년 11월 14일
0
post-custom-banner
  • Sequelize Associate 하면서 오류가 발생 했다.
  static associate(db) { // <- 테이블 join 하려고 작성
    db.Goods.belongsTo(db.User);
  }

위 코드를 작성하고 index.js(Model폴더) 작업하고 났는데 갑자기 아래와 같은 오류가 생겼다.

오류메세지 : original: Error: Duplicate column name 'UserId'

  1. 처음에는 이유를 몰라 오류메세지를 구글링했는데 관련 정보를 찾기가 어려웠고, 칼럼에 UserId가 중복되어 있다는 문구("Duplicate column name 'UserId'")를 보고 모델쪽 코드와 워크벤치를 보았다.
    코드는 중복입력한게 없는데 중복되어 있다고 나온다.

  2. 아래 오류메세지와 함께 적힌 sql문을 보면 UserId가 중복되어 들어간게 보이긴 했다. (굵게 표시함)
    "Duplicate column name 'UserId'",
    sql: "CREATE TABLE IF NOT EXISTS Goods (id INTEGER NOT NULL auto_increment , goods VARCHAR(255), content VARCHAR(255), userId INTEGER, status ENUM('for-sale', 'sold-out'), createdAt DATETIME NOT NULL, updatedAt DATETIME NOT NULL, deletedAt DATETIME, UserId INTEGER, PRIMARY KEY (id), FOREIGN KEY (UserId) REFERENCES Users (id) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;",

    알아보니 associate 할때 해당 모델과 연결하면서 UserId가 자동으로 생성되는듯 하였다. 그런데 아래 코드를 보면 기존에 내가 userId값을 저장하려고 만들어놓은 부분이 있다. 그래서 중복값이 생기면서 오류가 뜬것이었다.
    해당 코드를 지우고 다시 forse: true로 바꾸고 서버를 껐다 켰더니 오류가 해결되었다.

      {
        goods: Sequelize.STRING,
        content: Sequelize.STRING, 
        userId: Sequelize.INTEGER, // <- 이 부분
        status: Sequelize.ENUM('for-sale', 'sold-out'),
      },
      ....
      ....
     
}

어렵게 생각했지만 조금만 시퀄라이즈의 associate가 어떤 것이고 어떻게 기능을 하는지 알았더라면 이렇게 오래 헤매지는 않았을 것이라는 생각에 조금 더 공부를 하였다.

Sequelize Associate란 ?
Sequelize CLI 를 통해 Model을 정의하고, Migration으로 스키마를 관리하는 것이고
이때, RDBMS의 가장 중요한 Table 간의 관계를 Sequelize에서 Model 간의 관계로 정의하는 것

  • Sequelize 에서는 이러한 관계를 정의하기 위해 hasMany()와 belongsTo() 메소드를 지원하는데 (나의 프로젝트를 예로 들면)
    hasMany()는 여러개의 goods를 가지고
    belongsTo() : goods는 하나의 user에 속하는 것을 의미한다.
    경우에 따라 아래와 같이 작성한다.

  • 1 : 1
    hasOne();
    belongsTo();

  • 1 : N
    hasMany();
    belongsTo();

  • N : M
    belongsToMany()

static associate(db) {
      db.Goods.belongsTo(db.User, {
        as: "goods",
        foreignKey: "userId",
        onDelete: "cascade",
      });
    }

만약 위와 같이 코드를 작성했다면 아래와 같은 의미이다.

  • goods : user = n : 1 의 관계
  • as: "goods" -> goods라는 칼럼명을 쓰겠다
  • foreignKey: "userId"를 외부키로 쓰겠다 (작성하지 않으면 모델명 + Id를 디폴트 값으로 컬럼을 생성 ) -> 그래서 UserId칼럼이 나도 모르게 생성됬던 것
  • onDelete: "cascade" -> 1 : n 관계에 있는데 1에 해당하는 row가 삭제되는 경우 해당 n테이블의 row도 사라지게 함 (cascade 옵션을 설정할 후 부모 테이블의 row를 제거하면 부모를 FK로 가진 자식 그리고 자식을 FK로 가지고 있는 자손 즉, 부모와 연결된 모든 테이블의 row는 자동으로 삭제됨)
    -> 특정 유저의 아이디로 상품을 등록했는데 해당 유저가 탈퇴하는 경우 관련된 상품들도 함께 삭제되며 연결된 게시글 등도 있다면 함께 삭제 처리됨.
profile
더 많은 사람들이 더 좋은 정보와 서비스를 누릴 수 있게!!
post-custom-banner

0개의 댓글