[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 타입의 대리 키를 사용하는 것이 좋다.
Author And Source
이 문제에 관하여([DB] 테이블을 설계하자! -5), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@tjdud3550/DB-테이블을-설계하자-5저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)