- 객체지향은 상속관계가 존재하지만 RDB는 상속 관계가 없다.
- RDB에는 슈퍼타입/서브타입 관계같은 상속 관계와 비슷한 모델링 기법이 있다.
- 물품을 RDB 논리 모델링을 진행하는 경우 물품 > 음반, 영화, 책 → 공통된 데이터를 물품이 갖는다 (슈퍼타입 / 서브타입)
- 슈퍼타입/서브타입 → 객체 상속관계 변환 방법
- 조인 전략 : 슈퍼타입용 테이블과 서브타입 테이블을 따로 구성하고, 슈퍼타입 테이블에 구분 컬럼을 둔다. 정규화가 잘 된 테이블 전략이다.
- 단일 테이블 전략 (Default) : 서브타입 테이블 컬럼을 슈퍼타입 테이블 하나에 모은다. 구분 컬럼을 둔다. 성능적인 측면에서 장점이 있다.
- 구현 클래스 별 테이블 전략 : 슈퍼타입의 공통 데이터를 서브타입 테이블에 컬럼으로 넣어 사용한다.
조인 전략

- 정규화 모델링이 잘 된 테이블 전략
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Item{
@Id
@GeneratedValue
private Longid;
private Stringname;
private intprice;
}
@Entity
public class Movie extends Item {
private String director;
private String actor;
}
Movie movie = new Movie();
movie.setDirector("director A");
movie.setActor("actor B");
movie.setName("바람과 함께 사라지다.");
movie.setPrice(10000);
em.persist(movie);
- 각각 Movie 테이블과 Item 테이블에 저장되고 Item 테이블의 PK가 Movie 테이블의 PK이면서 FK가 된다.
- Movie를 조회하는 경우 Item을 JPA가 조인해서 가져온다.

- @DiscriminatorColumn 서브타입의 테이블 명이 슈퍼타입의 DTYPE 컬럼에 들어간다. 해당 데이터가 어떤 서브타입에서 들어오는지 확인할 수 있다.
- @DiscriminatorValue을 서브타입에 지정함으로써 테이블 명이 아닌 지정한 이름이 DTYPE에 들어가게 할 수 있다.
장점
- 외래키 참조 무결성 제약조건을 활용 가능하기 때문에 다른 테이블에서 조회하고자 하는 경우 슈퍼타입 클래스의 PK만 알면 서브타입까지 조회하는 것이 가능하다.
- 정규화가 되어있기 때문에 저장 공간에 있어 효율적이다.
단점
- 조회 시 조인을 많이 사용하기 때문에 성능 저하가 있다.
- 조회 쿼리가 복잡하고 insert 쿼리가 늘어난다.
단일 테이블 전략

- 서브타입 테이블이 많아지는 경우 단일 테이블 전략을 이용하는 것이 장점이 될 수 있다.
- 모든 컬럼을 슈퍼타입에 넣어 버리고 DTPYE을 이용해 어떤 서브타입의 데이터인지 구분한다.
- @Inheritance의 Default 전략이다.
- 조인이 없고, 데이터를 삽입할 때도 쿼리가 한번 밖에 안날아가기 때문에 성능적으로 장점이 있다.
- 어떤 서브타입의 데이터인지 구분할 수없기 때문에 @DiscriminatorColumn을 생략해도 자동으로 추가된다.


장점
- 하나의 테이블만 보고 조회를 할 수 있기 때문에 조회 쿼리가 단순하다.
- 조인이 필요없기 때문에 조회 성능이 빠르다.
단점
- 하나의 테이블로 사용하기 때문에 A 서브타입 데이터를 넣는 경우 B 서브타입의 데이터는 필요가 없고 데이터가 삽입되지도 않는다. 따라서, 서브타입 테이블 컬럼과 매핑한 엔티티는 모두 null을 허용한다.
- 테이블 데이터가 많아지거나 서브타입이 많아지는 경우 데이터가 늘어나 조회 성능이 나빠질 수도 있다.
구현 클래스 별 테이블 전략 (실사용 X)

- 슈퍼타입 테이블의 컬럼이 서브타입 테이블마다 포함되기 때문에 슈퍼타입 테이블이 존재하지 않는다.
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
를 이용한다.@DiscriminatorColumn
이 필요가 없다.- 상위 클래스 타입으로 데이터를 조회하는 경우 JPA는 모든 서브타입 테이블을 union으로 가져와 조회하기 때문에 복잡하다.
장점
- 서브타입을 명확하게 구분해서 처리할 수 있고, 구분되어 있기 때문에 Not Null을 사용하는 것이 가능하다.
단점
- 여러 서브타입 테이블을 함께 조회할 때 Union을 이용한 쿼리를 실행하기 때문에 성능이 느리다.
- 자식 테이블을 통합해서 쿼리를 실행하는 것이 복잡하다.
조인 전략? 단일 테이블 전략?
- 조인 전략을 기본으로 선택해놓고, 해당 테이블이 확장 가능성 여부와 중요 여부를 판단해 단일 테이블 전략을 추후 선택하는 것을 권장한다.
@MappedSuperclass
- DB내 테이블은 다른 테이블이지만 각 테이블에 공통되는 컬럼이 있어 객체입장에서는 공통 필드로 빼고 싶은 경우에 사용한다.
- 상속관계 매핑이 아니다!
- 직접 생성하고 조회 및 검색이 불가능하기 때문에 추상 클래스로 사용한다.
- 부모 클래스를 상속받는 자식 클래스에 매핑 정보만 제공한다. 제공된 컬럼은 자식 엔티티와 매핑되는 테이블에 모두 포함된다.
@MappedSuperclass
public abstract class BaseEntity {
//== 모든 테이블에 아래의 속성이 필수로 들어가야하는 경우 - 속성만 상속받아 사용 ==//
private String createdBy;
private LocalDateTime createdDate;
@Column(name = "UPDATED_MEMBER")
private String lastModifiedBy;
private LocalDateTime lastModifiedDate;
}
- 위의 BaseEntity 속성들이 BaseEntity를 상속받은 모든 엔티티 테이블에 포함된다.
- JPA에서 엔티티가 상속을 받기 위해서는 @Entity 혹은 @MappedSuperclass가 붙어있는 엔티티 클래스만 상속이 가능하다.
📃 References
김영한님의 자바 ORM 표준 JPA 프로그래밍 - 기본편 : https://www.inflearn.com/course/ORM-JPA-Basic/dashboard
반응형
'Backend > JPA' 카테고리의 다른 글
즉시 로딩과 지연 로딩 (0) | 2022.07.21 |
---|---|
프록시 (0) | 2022.07.20 |
엔티티 설계의 주의사항 간단 정리 (0) | 2022.07.05 |
다양한 연관관계 매핑 (0) | 2022.05.02 |
단방향, 양방향 매핑 (0) | 2022.04.26 |