
상속관계 매핑
관계형 데이터베이스는 상속 관계를 매핑할 수 없다. 그나마 관계형 데이터베이스에는 슈퍼타입 - 서브타입 관계가 존재하여 객체의 상속과 비슷하므로 이를 사용해 객체의 상속을 매핑할 수 있다.
슈퍼타입 서브타입 논리 모델을 실제 물리 모델로 변환하는 방법
- 테이블 join 전략 사용 - 정규화된 방식
- 물품 - 책, 영화, 음반 간의 부모 - 자식 관계가 있다면 각각의 테이블을 만들어 부모_ID를 FK로 만들어 조인하여 사용하는 방법.
- 단일 테이블 전략 사용 - 보통 성능을 위한 방식
- 통합 테이블을 구성하여 하위 테이블의 모든 컬럼을 넣는 방법
- 서브타입 테이블 전략 사용 - 부모 테이블 없이 자식 테이블로만 정리
- 구현 클래스마다 테이블 사용하는 방법
기본적으로 아무런 어노테이션이 없을 때는 단일 테이블 전략으로 만들어짐.
주요 Annotation
- @Inheritance(strategy=InheritanceType.XXX)
- JOINED: 조인 전략
- 장점
- 테이블 정규화
- 외래 키 참조 무결성 제약조건 활용가능
- 저장공간 효율화
- 단점
- 조회시 조인을 많이 사용 -> 성능저하 but, 조인에 따라서 성능저하가 작을 수 도 있음.
- 조회 쿼리가 복잡함
- 데이터 저장시 INSERT SQL 2번 호출
- 장점
- SINGLE_TABLE: 단일 테이블 전략
- 장점
- 조인이 필요 없으므로 일반적으로 조회 성능이 빠름
- 조회 쿼리가 단순함
- 단점
- 자식 엔티티가 매핑한 컬럼은 모두 null 허용
- 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다. 상황에 따라서 조회 성능이 오히려 느려질 수 있다. -> 보통 이런 일이 생기기 힘듬.(임계점을 넘어야함)
- 장점
- TABLE_PER_CLASS: 구현 클래스마다 테이블 전략
- 이 전략은 데이터베이스 설계자와 ORM 전문가 둘 다 추천X
- 부모 클래스를 abstract로 만들시 부모 테이블이 생기지 않음.
- 장점
- 서브 타입을 명확하게 구분해서 처리할 때 효과적
- not null 제약조건 사용 가능
- 단점
- 여러 자식 테이블을 함께 조회할 때 성능이 느림(UNION SQL 필요) -> 1번 id를 찾으려면 자식 테이블 모두 찾아봐야함.
- 자식 테이블을 통합해서 쿼리하기 어려움
- JOINED: 조인 전략
- @DiscriminatorColumn(name=“DTYPE”)
- 어느 자식테이블과 조인되어 있는지 알려주는 컬럼의 이름을 설정하는 어노테이션
- SINGLE_TABLE 전략일 때는 없어도 생성됨
- @DiscriminatorValue(“XXX”)
- DTYPE에 들어갈 자식 클래스의 이름을 지정하는 어노테이션
@DiscriminatorColumn(name=“DTYPE”)
기본값으로 "DTYPE"이 지정된다. 없어도 작동하는데에는 문제없지만 DB에서의 작업할 때 쿼리가 어떤 것 때문에 나갔는지 확인할 수 있기 때문에 넣어두는 것이 좋다.
| @DiscriminatorColumn 추가 전 | @DiscriminatorColumn 추가 후 |
![]() |
![]() |
@DiscriminatorValue(“XXX”)
사내 특정 DB 룰이 있어 변경해야 할 경우에 사용할 수 있다.
만약 Album 클래스의 DTYPE을 A로 표시하고 싶다면 다음과 같이 작성하면 된다.
@Entity
@DiscriminatorValue(value = "A")
public class Album extends Item {
private String artist;
...
}
위의 예제 영화로 변경하게 되면 다음과 같에 DB에 저장되게 된다.

Mapped Superclass - 매핑 정보 상속
두 클래스, 두 테이블의 관계는 없지만 id, name과 같이 공통 속성이 존재할 때 사용하는 어노테이션이다.
만약, 모든 엔티티에서 생성되고 수정된 시각과 생성자 및 수정자의 정보를 기입하도록 정책이 변경되었을 때 우리는 다음과 같은 정보들을 모든 엔티티에 일일히 넣어야할 것이다.
private String createdBy;
private LocalDateTime createdDate;
private String lastModifiedBy;
private LocalDateTime lastModifiedDate;
이런 상황에서 `@MappedSuperclass` 어노테이션을 활용하여 처리할 수 있다.
먼저 다음과 같은 공통 속성이 추려진 클래스를 만들고 이 클래스의 속성을 사용하고 싶은 클래스에서 상속받으면 사용할 수 있다.
@MappedSuperclass
public abstract class BaseEntity {
private String createdBy;
private LocalDateTime createdDate;
private String lastModifiedBy;
private LocalDateTime lastModifiedDate;
...
}
Mapped Superclass는 실제 엔티티가 아니므로 테이블이 생성되지 않는다. 부모 클래스를 상속받는 자식 클래스에게 속성 정보만 제공하기 때문에 EntityManager로 검색 조회가 불가능하다. 이 엔티티를 직접 사용할 일이 없으므로 추상 클래스로 작성하여 사용하자.
'노트 정리 > 자바 ORM 표준 JPA 프로그래밍' 카테고리의 다른 글
| [JPA이론] 9.값 타입 (0) | 2022.10.20 |
|---|---|
| [JPA이론] 8. 프록시와 연관관계 관리 (0) | 2022.10.19 |
| [JPA이론] 6. 다양한 연관관계 매핑 (0) | 2022.10.13 |
| [JPA이론] 5. 연관관계 매핑 기초 (0) | 2022.10.09 |
| 4. 엔티티 매핑 (0) | 2022.08.24 |

