두번째 내용인 hasOne() 관계에 대한 포스팅이다.
이전 글과 마찬가지로 http://docs.sequelizejs.com/manual/tutorial/associations.html 이 글에서
hasOne() 부분만 따로 가져와서 번역했다.
HasOne
hasOne은 1:1관계에 대한 외래키가 target 모델에 있을 때 사용한다.
const User = sequelize.define('user', {/* ... */}) const Project = sequelize.define('project', {/* ... */}) // One-way associations Project.hasOne(User) /* 이번 예제에서 hasOne은 User모델에 projectId 컬럼을 추가할 것이다. 게다가 Project.prototype은 define을 통해 들어오는 첫번째 인자에 따라 getUser와 setUser라는 메소드를 얻게 된다. 만약 underscore 옵션을 줬다면 projectId 대신 project_id라는 컬럼이 생성된다. 외래키는 users 테이블에 생성된다. 또한 외래키를 직접 지정할 수 있다. */ Project.hasOne(User, { foreignKey: 'initiator_id' }) /* Sequelize는 define()의 첫번째 파라미터를 유저 모델에 있는 accessor 메소드의 이름으로 사용하기 때문에 hasOne()에 특별한 옵션을 줄수도 있다. */ Project.hasOne(User, { as: 'Initiator' }) // 이제 Project.getInitiator와 Project.setInitiator 메소드를 사용할 수 있다. // 또는 특정한 자체 참조를 사용할수도 있다. const Person = sequelize.define('person', { /* ... */})
// 이번에는 자기 참조에 관한 예제를 만들어보자. Person.hasOne(Person, {as: 'Father'}) // 위 라인은 FatherId 컬럼을 Person 모델에 추가한다. // 또한 아래처럼 사용할수도 있다: Person.hasOne(Person, {as: 'Father', foreignKey: 'DadId'}) // 위 라인은 DadId 컬럼을 Person 모델에 추가한다. // 아래 두개의 메소드를 사용할 수 있다: Person.setFather Person.getFather // 만약 두번의 join을 사용하고 싶다면, 같은 테이블을 사용하면 된다. Team.hasOne(Game, {as: 'HomeTeam', foreignKey : 'homeTeamId'}); Team.hasOne(Game, {as: 'AwayTeam', foreignKey : 'awayTeamId'}); Game.belongsTo(Team);
대부분의 경우 BelongsTo는 source로 지정된 target모델에 자동으로 외래키를 생성하기 때문에 1:1관계에서는 BelongsTo를 설정해주는 것이 좋다.
HasOne과 BelongsTo의 차이점
Sequelize에서 1:1관계는 HasOne과 BelongsTo로 설정해줄 수 있다. 두가지 모두 각각이 적합한 상황이 있다.
이번 예제를 통해 둘의 차이점에 대해서 살펴본다.
Player와 Team이라는 두개의 테이블이 있다고 가정해보자.
const Player = this.sequelize.define('player', {/* attributes */})
const Team = this.sequelize.define('team', {/* attributes */});
Sequelize에서 두개의 모델을 연결해주려면 source와 target을 사용하면 된다.
아래를 보면 Player는 source이고 Team은 target이다.
Player.belongsTo(Team);
//Or
Player.hasOne(Team);
아래는 Team을 source로 삼고 Player를 target으로 삼는다.
Team.belongsTo(Player);
//Or
Team.hasOne(Player);
HasOne과 BelongsTo는 관계키를 각각 다른 모델에 생성한다.
HasOne은 관계키를 target모델에 생성하는 반면 BelongsTo는 source모델에 생성한다.
아래 예제를 통해 BelongsTo와 HasOne의 동작에 대해 살펴본다.
const Player = this.sequelize.define('player', {/* attributes */})
const Coach = this.sequelize.define('coach', {/* attributes */})
const Team = this.sequelize.define('team', {/* attributes */});
Player 모델이 팀에 대한 정보를 가지고 있는 teamId 컬럼을 가지고 있다고 가정해보자.
각 팀의 코치에 대한 정보는 Team 모델의 coachId 컬럼으로 존재한다.
각각 다른 모델에 외래키 관계가 존재하기 때문에 이 두개의 시나리오는 다른 종류의 1:1 관계가 필요하다.
만약 관계에 대한 정보가 source 모델에 존재한다면 우리는 belongsTo를 사용할 수 있다.
아래의 경우, Player는 teamId 컬럼을 가지고 있기 때문에 belongsTo가 적합하다.
Player.belongsTo(Team) // `teamId` 는 Player(source 모델)에 생성된다.
하지만 관계에 대한 정보가 target 모델에 존재한다면 hasOne을 사용해야 한다.
아래의 경우, Team 모델이 Coach에 대한 정보를 coachId라는 컬럼으로 가지고 있기 때문에 hasOne이 적합하다.
Coach.hasOne(Team) // `coachId` 는 Team(target 모델)에 생성된다.