상속관계매핑(객체의 상속관계를 어떻게 DB에 매핑하는지)
원래 관계형 DB는 상속관계라는것이 없다. 대신 이와 유사하게 슈퍼타입-서브타입 관계라는 모델링 기법이 객체 상속과 유사하다.
상속관계 매핑이란 (객체의 상속구조) - (Db의 슈퍼타입-서브타입 관계)를 매핑
슈퍼타입-서브타입 논리모델을 실제 물리모델로 구현하는 방법은 총 3가지가 있다.
1. 각 테이블로 변환 -> join전략
오른쪽에 DB를 보면 ITEM_ID를 통해 Join을통해 필요하면 조회하는 방식.
이런방식은 item,(album/movie/book) 에 insert를 각가해줘야하고
ITEM_ID라는 개인키를통해 join 해서 조회를 한다.
item이 앨범인지 북인지 영화인지 구분하기위해 DTYPE을 통해 구분한다.
장점:
- 테이블이 정규화되어있다.
- 외래키 참조 무결성 제약조건 활용가능 -> item_id를 통해 다른 테이블 접근이 가능하므로 item테이블만으로 조회가 가능.
- 저장공간 효율화
단점
- 조회시 조인을 많이사용(성능저하)
- 조회 쿼리가 복잡
- 데이터 저장시 insert sql이 2번 호출
2. 통합 테이블로 변환 -> 단일 테이블 전략
하나의 테이블로 합쳐버린다.
item이 앨범인지 북인지 영화인지 구분하기위해 DTYPE을 통해 구분한다.
장점
- 조인 필요없어서 조회성능이 빠르다.
- 조회 쿼리가 단순
단점
- 자식 Entity가 매핑한 컬럼은 모두 null 허용
- 모든것을 하나의 테이블로 저장해서 테이블이 커진다.
3. 서브타입 테이블로 변환 -> 구현클래스마다 테이블 전략
추상방식이 아닌 구현클래스 마다 각각 나누어서 DB 설계를 한다.
결론부터 말하면 이건 쓰면 안된다!!! (DB설계자 와 ORM 전문가 둘다 추천하지않는다.)
장점
- 서브타입을 명확히 구분해서 처리할떄 효과적
- not null 제약조건 사용가능
단점
- 여러 자식테이블을 함께 조회할떄 성능이 느림(Union sql)
- 자식테이블을 통합해서 쿼리하기가 어려움.
DB설계시 1,2,3방법중 어떤 방법을 사용하든 객체와 매핑이 가능하다.!!!
ITEM 클래스 | |
@Entity (JPA는 기본적략이 2번 단일테이블 전략이다) (join이나 insert가 부모,자식에 각각 들어가는상황같은게 없어서 성능이 가장 잘나온다.) |
|
1번 @Entity @Inheritance(strategy=InheritanceType.JOINED) |
|
부모 클래스(Item)에서 사용 @Entity @DiscriminatorColumn 참고: name 속성으로 칼럼명 Dtype말고 다른걸로 바꿀수있다. 자식클래스(Movie)에서 사용 @Entity @DiscriminatorValue("M") |
Dtype이 컬럼으로 자동으로 추가된다. Movie말고 M 으로 바꾸고싶으면 DiscriminatorValue 사용 |
3번 @Entity @Inheritance(strategy= InheritanceType.TABLE_PER_CLASS) |
이것을 사용할떄 abstract class Item으로 추상클래스로 만들고 사용. Item테이블이 안만들어지고 Movie, Album, Book각각 만들어짐. |
@MappedSuperClass
- 테이블과 관계없고 단순히 엔티티가 공통으로 사용하는 매핑정보를 모으는 역할
객체입장에서 생각하면 id, name이 중복된게 계속해서 나오면 부모클래스로 두고 상속해서 쓰고싶어진다.
MappedSuperclass을 써서 속성만 상속해서 사용할수있다. (DB는 구조상 변화없음)
package hellojpa;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;
@MappedSuperclass
public abstract class BaseEntity {
private String createdBy;
private LocalDateTime createdDate;
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public LocalDateTime getCreatedDate() {
return createdDate;
}
public void setCreatedDate(LocalDateTime createdDate) {
this.createdDate = createdDate;
}
}
public class Team extend BaseEntity {}
public class Member extend BaseEntity {}
member, team 에서 BaseEntity의 속성들만 상속받아서 사용할떄 주로 사용.(DB에는 각각 createBy, createDate를 갖고있다.)
- 주의: 상속관계 매핑이 아니라서 테이블과 매핑 안됨, 엔티티가 아니라서 조회,검색같은게 안된다. (em.find(BaseEntity) 이런거 사용불가)
- 직접 생성해서 사용할일 없어서 추상클래스에 사용 권장.
- 부모클래스를 상속받는 자식클래스에 매핑정보만 제공!
- 주로 등록일,수정일,등록자,수정자같은 전체 엔티티에서 공통으로 적용하는 정보를 모을떄 사용.
- 참고: @Entity 클래스는 @Entity/@MappedSuperclass가 붙은 클래스만 상속가능!
'𝗦𝗣𝗥𝗜𝗡𝗚 > 𝐎𝗥𝗠-𝗝𝗣𝐀' 카테고리의 다른 글
다양한 연관관계 매핑 (0) | 2024.01.03 |
---|---|
연관관계 매핑 기초 (0) | 2024.01.03 |
엔티티 매핑 (0) | 2024.01.02 |
JPA 영속성 컨텍스트 (0) | 2023.12.27 |
JPA 구동방식 (0) | 2023.12.27 |