[DB] 테이블을 설계하자! -5

복합 키: 식별 관계 매핑

부모, 자식, 손자까지 기본 키를 전달하고 있다. 식별 관계에서 자식 테이블은 부모 테이블의 기본 키를 포함해서 복합 키를 구성해야 한다.

@IdClass와 식별 관계

@Entity
public class Parent {

    @Id
    @Column(name = "PARENT_ID")
    private String id;

    private String name;

}

@Entity
@IdClass(ChildId.class)
public class Child {

    @Id
    @ManyToOne
    @JoinColumn(name = "PARENT_ID")
    public Parent parent;

    @Id
    @Column(name = "CHILD_ID")
    private String childId;

    private String name;

}

public class ChildId implements Serializable {

    private String parent; // Child.parent 매핑
    private String childId; // Child.childId 매핑

    // 생성자
    // equals, hashCode

}

@Entity
@IdClass(GrandChildId.class)
public class GrandChild {

    @Id
    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "PARENT_ID")
            @JoinColumn(name = "CHILD_ID")
    })
    private Child child;

    @Id
    @Column(name = "GRANDCHILD_ID")
    private String id;

    private String name;

}

public class GrandChildId implements Serializable {

    private ChildId child; // GrandChild.child 매핑
    private String id; // GrandChild.id 매핑

    // 생성자
    // equals, hashCode

}

@EmbeddedId와 식별 관계

@Entity
public class Parent {

    @Id
    @Column(name = "PARENT_ID")
    private String id;

    private String name;

}

@Entity
public class Child {

    @EmbeddedId
    private ChildId id;

    @MapsId("parentId") // ChildId.parentId 매핑
    @ManyToOne
    @JoinColumn(name = "PARENT_ID")
    public Parent parent;

    private String name;

}

@Embeddable
public class ChildId implements Serializable {

    private String parentid; // @MapsId("parentId")로 매핑

    @Column(name = "CHILD_ID")
    private String id;

    // 생성자
    // equals, hashCode

}

@Entity
public class GrandChild {

    @EmbeddedId
    private GrandChildId id;

    @MapsId("childId") // GrandChildId.childId 매핑
    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "PARENT_ID"),
            @JoinColumn(name = "CHILD_ID")
    })
    private Child child;

    private String name;

}

@Embeddable
public class GrandChildId implements Serializable {

    private ChildId childid; // @MapsId("childId")로 매핑

    @Column(name = "GRANDCHILD_ID")
    private String id;

    // 생성자
    // equals, hashCode

}

아래와 같이 Child 엔티티의 parent 필드는 @Id 대신에 @MapsId를 사용하였다. @MapsId는 외래 키와 매핑한 연관 관게를 기본 키에도 매핑하겠다는 뜻이다. @MapsId의 속성 값은 @EmbeddedId를 사용한 식별자 클래스의 기본 키 필드를 지정하면 된다.

    @MapsId("parentId") // ChildId.parentId 매핑
    @ManyToOne
    @JoinColumn(name = "PARENT_ID")
    public Parent parent;
   

비식별 관계로 구현

@Entity
public class Parent {

   @Id
   @GeneratedValue
   @Column(name = "PARENT_ID")
   private Long id;

   private String name;

}

@Entity
public class Child {

   @Id
   @GeneratedValue
   @Column(name = "CHILD_ID")
   private Long id;

   private String name;

   @ManyToOne
   @JoinColumn(name = "PARENT_ID")
   private Parent parent;

}

@Entity
public class GrandChild {

   @Id
   @GeneratedValue
   @Column(name = "GRANDCHILD_ID")
   private Long id;

   private String name;

   @ManyToOne
   @JoinColumn(name = "CHILD_ID")
   private Child child;

}

훨씬 간결하다.~~~!!!!

일대일 식별 관계

일대일 식별 관계는 자식 테이블의 기본 키 값으로 부모 테이블의 기본 키 값만 사용한다. 그래서 부모 테이블의 기본 키가 복합 키가 아니면 자식 테이블의 기본 키는 복합 키로 구성하지 않아도 된다.

@Entity
public class Board {

    @Id
    @GeneratedValue
    @Column(name = "BOARD_ID")
    private Long id;

    private String title;

    @OneToOne(mappedBy = "board")
    private BoardDetail boardDetail;

}

@Entity
public class BoardDetail {

    @Id
    private Long boardId;

    @MapsId // BoardDetail.boardId 매핑
    @OneToOne
    @JoinColumn(name = "BOARD_ID")
    private Board board;

    private String content;

}

식별, 비식별 관계의 장단점

식별 관계

장점
-기본 키 인덱스를 활용하기 좋다.
-상위 테이블의 기본 키 컬럼을 자식, 손자 테이블이 가지고 있으므로 특정 상황에 조인 없이 검색이 가능하다.

단점
-부모 테이블의 기본 키를 자식 테이블로 전파하면서 자식 테이블의 기본 키 컬럼이 점점 늘어난다.

-부모 테이블은 1개, 자식 테이블은 2개, 손자 테이블은 3개, ....과 같은 상황에서 조인할 때 SQL이 복잡해지고 기본 키 인덱스가 불필요하게 커질 수 있다.

-기본 키로 비즈니스 의미가 있는 자연 키 컬럼을 사용한다.
-비즈니스 요구가 바뀌면 엄청난 코드 수정이 필요하다.
-테이블 구조가 유연하지 않다.
-일대일 관계를 제외하고 별도의 복합 키 클래스를 만들어야 한다.

비식별 관계는 위의 장단점을 바꾸어서 생각하면 된다. 결국 ORM 신규 프로젝트 진행 시 될 수 있으면 필수적 비식별 관계를 사용하고 기본 키는 Long 타입의 대리 키를 사용하는 것이 좋다.

좋은 웹페이지 즐겨찾기