본문 바로가기

스터디/JPA

고급 매핑 - (2)

728x90
반응형

복합 키와 식별 관계 매핑


식별 관계 vs 비식별 관계

테이블 사이의 관계에는 외래 키가 기본 키에 포함되는지 여부에 따라 식별 관계와 비식별 관계로 구분한다

 

식별 관계부모 테이블의 기본 키를 받아서 자식 테이블의 기본 키 + 외래 키로 사용하는 관계이다

비식별 관계부모 테이블의 기본 키를 받아서 자식 테이블의 외래 키로만 사용하는 관계이다

 

필수적 비식별 관계외래 키에 null을 허용하지 않는다 즉, 연관관계를 필수적으로 맺어야 한다

선택적 비식별 관계외래 키에 null을 허용한다 연관관계를 맺을지 말지 선택할 수 있다

 

최근에는 비식별 관계를 주로 사용하고 꼭 필요할 곳에만 식별 관계를 사용하는 추세이다

복합 키: 비식별 관계 매핑

JPA는 복합 키를 지원하기 위해 @IdClass와 @EmbeddedId 두 가지 방법을 제공한다

 

복합 키의 비식별 관계 매핑은 다음과 같이 구현된다

 

1. @IdClass

@Entity
@IdClass(ParentId.class)
public class Parent {

	@Id
	@Column(name="PARENT_ID1")
	private String id1;
	
	@Id
	@Column(name="PARENT_ID2")
	private String id2;
	
	private String name;
	...
}
public class ParentId implements Serializable {
	
	private String id1;
	private String id2;
	
	public ParentId() {}
	
	public ParentId(String id1, String id2) {
		this.id1 = id1;
		this.id2 = id2;
	}
	
	@Override
	public boolean equals(Object o) { ... }
	
	@Override
	public int hashCode() { ... }
}
@Entity
public class Child {
	
	@Id
	private String id;
	
	@ManyToOne
	@JoinColumns({
		@JoinColumn(name="PARENT_ID1"),
		@JoinColumn(name="PARENT_ID2")		
	})
	private Parent parent;
}

부모의 기본 키를 받아 외래 키로만 사용하고 있으므로 비식별 관계이다

 

2. @EmbeddedId

@Entity
public class Parent {

	@EmbeddedId
	private ParentId id;
	
	private String name;
	...
}
@Embeddable
public class ParentId implements Serializable {
	
	@Column(name="PARENT_ID1")
	private String id1;
	@Column(name="PARENT_ID2")
	private String id2;
	...
}

 

@IdClass에 비해 객체 지향적이고 중복도 없다는 장점이 있지만 특정 상황에서 JPQL이 길어질 수 있다

em.createQuery("select p.id.id1, p.id.id2 from Parent p")
em.createQuery("select p.id1, p.id2 from Parent p")

복합 키: 식별 관계 매핑

복합 키의 식별 관계 매핑은 다음과 같이 구현된다

 

1. @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")
	private Parent parent;
	
	@Id
	@Column(name="CHILD_ID")
	private String childId;
	
	private String name;
	...
}

@Id로 기본 키를 매핑하면서 @ManyToOne@JoinColumn으로 기본 키와 외래 키를 같이 매핑한다

 

2. @EmbeddedId

@Entity
public class Child {

	@EmbeddedId
	private ChildId id;
	
	@MapsId("parentId")
	@ManyToOne
	@JoinColumn(name="PARENT_ID")
	public Parent parent;
	
	private String name;
	...
}

@IdClass와 다르게 식별 관계로 사용할 연관관계의 속성에 @MapsId를 사용한다

  - 외래 키와 매핑한 연관관계를 기본 키에도 매핑하겠다는 의미이다

 

비식별 관계로 구현하는 것이 식별 관계의 복합 키를 사용한 코드와 비교해보면 매핑도 쉽고 코드도 단순하며,

복합 키 클래스를 구현하지 않아도 된다

-> 비식별 관계로 구현하는 것을 추천한다

일대일 식별 관계

일대일 식별 관계는 자식 테이블의 기본 키 값으로 부모 테이블의 기본 키 값만 사용한다 (유니크 하므로)

부모 테이블의 기본 키가 복합 키가 아니면 자식 테이블의 기본 키가 복합 키가 아니어도 된다

 

@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
	@OneToOne
	@JoinColumn(name="BOARD_ID")
	private Board board;
	
	private String content;
	...
}

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

 

장점

 

1. 기본 키 인덱스를 활용하기 좋다

  - 상위 테이블의 기본 키 컬럼을 자식, 손자 테이블이 가지고 있으므로 특정 상황에 조인 없이 하위 테이블만으로 검색을 완료할 수 있다

 

 

단점

 

1. 식별 관계는 부모 테이블의 기본 키를 자식 테이블로 전파하면서 자식 테이블의 기본 키 컬럼이 점점 늘어난다

  - 조인 시 SQL이 복잡해지고 기본 키 인덱스가 불필요하게 커질 수 있다

 

2. 식별 관계는 2개 이상의 컬럼을 합해 복합 기본 키를 만들어야 하는 경우가 많다

  - 별도의 복합 키 클래스를 만들어 사용해야 하므로 많은 노력이 필요하다

 

3. 식별 관계를 사용하는 경우 비즈니스 의미가 있는 컬럼을 조합하는 경우가 많다

  - 컬럼이 자식까지 전파되면 비즈니스 요구사항이 변경될 때 변경하기 힘들다

 

4. 식별 관계는 부모 테이블의 기본 키를 자식 테이블의 기본 키로 사용하므로 테이블 구조가 유연하지 못하다

 

비식별 관계를 사용하고 기본 키는 Long 타입의 대리 키를 사용하는 것을 추천한다 (920경)

  - Integer는 많은 데이터를 저장하면 문제가 발생할 수 있다 (20억)

728x90
반응형

'스터디 > JPA' 카테고리의 다른 글

프록시와 연관관계 정리 - (1)  (0) 2025.02.13
고급 매핑 - (3)  (0) 2025.02.12
고급 매핑 - (1)  (0) 2025.02.11
다양한 연관관계 매핑 - (3)  (0) 2025.02.11
다양한 연관관계 매핑 - (2)  (0) 2025.02.10