일대다

  • 1이 연관 관계의 주인

    • 추천하지 않는 방법이다.

단방향

  • team을 중심으로 member를 관리한다.

    • member는 team을 모른다.

  • DB 입장에서는 무조건 N에 외래키가 들어간다.

    • 1에 해당하는 team에 member_id가 PK로 있으면 team을 계속 insert 해야 해서 중복되는 이상한 상황이 나온다.

  • 일대다는 객체에선 team이 중심인데도 DB 입장에서는 N에 외래키가 있으므로 member 테이블을 건드려야 한다.

    • Team.members를 수정하면 team 테이블 대신 member 테이블에 있는 외래키 team_id를 업데이트 한다.

@Entity
public class Team {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "TEAM_ID")
    private Long id;

    // 1에서 N을 참조한다.
    @OneToMany
    @JoinColumn(name = "TEAM_ID")
    private List<Member> members = new ArrayList<>();
}

일단 각각 새 데이터를 만들었으니 insert 쿼리가 나간다.

이후 member 테이블에 대한 update 쿼리가 찍힌다. 비즈니스 로직만 보면 team만 손을 댄 것 같은데 쿼리를 보니 엉뚱한 member 테이블 update 쿼리가 나가서 혼란이 생긴다. 실무에서는 수 많은 테이블이 있기 때문에 더 다루기 힘들다.

일대다 대신 다대일로 하면 member가 team을 참조할 일이 없을 경우 객체 지향으로는 손해다. 하지만 JPA에서는 잘 사용할 수 있다. DB의 방향에 조금 더 맞춰 유지 보수를 호율적으로 할 수 있다.

정리

  • 1:N에서 1이 연관 관계의 주인이다.

  • 하지만 테이블의 1:N 관계는 항상 N에 외래키가 있다.

    • 객체와 테이블의 차이 때문에 반대편 테이블의 외래 키를 관리하는 특이한 구조가 된다.

  • @JoinColumn을 꼭 사용해야 한다.

    • 사용하지 않으면 조인 테이블 방식이 적용된다.

      • team_member 라는 중간 테이블이 생겨버린다.

      • 테이블이 하나 더 생기면 운영이 힘들다.

  • 엔티티가 관리하는 외래키가 다른 테이블에 있어 update SQL을 추가로 실행해야 하는 단점이 있다.

  • 일대다 단방향 매핑이 필요하다면 다대일 양방향 매핑을 사용하자.

양방향

  • Team.members가 연관 관계의 주인이다.

  • Member가 team을 읽기 전용으로 참조하려면 약간의 야매가 필요하다.

@Entity
public class Team {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "TEAM_ID")
    private Long id;

    @OneToMany
    @JoinColumn(name = "TEAM_ID")
    private List<Member> members = new ArrayList<>();
}
  • 둘 다 team_id를 참조하는 연관 관계의 주인이 되어버린다.

  • 이러면 어디가 기준인지 모르기 때문에 insertable과 updateble로 읽기 전용을 강제한다.

정리

  • 이런 매핑은 공식적으로 존재하지 않는다.

  • 읽기 전용 필드를 사용해 양방향처럼 사용한다.

  • 그냥 다대일 양방향을 사용하자.

Last updated