관계형 데이터베이스는 상속관계가 따로있지는 않지만 데이터베이스의 슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사하다.
상속관계 매핑이란 객체의 상속 구조와 DB의 슈퍼타입 서브타입관계를 매핑하는것을 말한다.
상속관계 매핑에는 3가지 방법이 존재한다.
- 각각 테이블로 변환 -> 조인 전략
- 통합 테이블로 변환 -> 단일 테이블 전략
- 서브타입 테이블로 변환 -> 구현 클래스마다 테이블 전략
먼저 조인 전략을 다이어그램과 코드로 표현하면 다음과 같다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn // 서브타입을 나타내는 속성값이 테이블에 추가됨
public class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
}
@Entity
public class Album extends Item {
private String artist;
}
@Entity
public class Movie extends Item {
private String director;
private String actor;
}
@Entity
public class Book extends Item {
private String author;
private int isbn;
}
조인 전략은 테이블이 정규화 되있고, 외래키 참조 무결성 제약조건이 활용가능하며 저장공간이 효율적이다.
하지만 조회시 조인을 많이 사용하여 성능이 저하되고, 조회 쿼리가 복잡하며, 데이터 저장시 insert 쿼리가 2번 호출된다.
다음으로 단일 테이블 전략이 있다.
단일 테이블 전략은 자식 엔티티의 모든 속성들을 부모 테이블에 몰아넣는 방식으로 상속관계를 구현한다.
단일 테이블 전략을 표현하는 다이어그램과 코드는 다음과 같다.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn // 없어도 DTYPE속성 생김
public class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
}
@Entity
public class Album extends Item {
private String artist;
}
@Entity
public class Movie extends Item {
private String director;
private String actor;
}
@Entity
public class Book extends Item {
private String author;
private int isbn;
}
단일 테이블 전략은 조인이 필요 없으므로 일반적으로 조회 성능이 빠르고 조회 쿼리 또한 단순하다.
반면 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 하며, 단일 테이블이 커져 조회성능이 오히려 느려질 수 있다.
마지막으로 구현 클래스마다 테이블 전략이 있는데, 여러 자식 테이블을 함께 조회할 때 성능이 느리고 자식 테이블을 통합해서 쿼리하기 어렵다.
이러한 단점들로 인해 해당 전략은 데이터베이스 설계자와 ORM 전문가 양쪽다 사용하기 꺼려하므로 대부분의 경우 사용하지 않는것이 바람직하다.
다음으로 설명할것은 @MappedSuperclass이다.
@MappedSuperclass는 공통 매핑 정보가 필요할 때 사용된다.
예를들어 대부분의 엔티티에 해당 객체가 만들어진 날짜(craetedDate)와 마지막 수정 날짜(lastModifiedBy)가 공통적으로 들어간다고 해보자.
이 경우 엔티티 하나하나마다 공통 필드를 추가하는것보다 추상클래스를 만들어 상속하는 식으로 구현하는것이 훨씬 효율적이다.
여기서 추상클래스 역할을 하는것에 @MappedSuperclass를 사용하면 된다.
@MappedSuperclass를 구현하는 코드는 다음과 같다.
@MappedSuperclass
public abstract class BaseEntity {
private LocalDateTime createdDate;
private LocalDateTime lastModifiedDate;
... // get set 구현
}
@Entity
public class otherEntity extends BaseEntity {
...
}
@MappedSuperclass는 자식 클래스에 매핑 정보만 제공하므로 조회나 검색은 불가능하다.(em.find(BaseEntity) 불가)
또한 직접 생성해서 사용할 일이 없으므로 추상 클래스로 작성하는걸 권장한다.
참고: 자바 ORM 표준 JPA 프로그래밍 (https://www.inflearn.com/course/ORM-JPA-Basic#)
'JPA' 카테고리의 다른 글
[JPA] 프록시와 즉시로딩, 지연로딩 (0) | 2022.01.05 |
---|---|
[JPA] 연관관계 매핑 (다대일, 일대다, 일대일, 다대다) (0) | 2022.01.03 |
[JPA] 연관관계 매핑(단방향, 양방향) (0) | 2021.12.27 |
[JPA] 영속성 관리 (영속성 컨텍스트) (0) | 2021.10.23 |