jpa 상속관계 맵핑
상속관계의 구현
- 객체에서의 상속과 같은 개념은 관계형 데이터베이스에 존재하지 않는다.
- 다만, 슈퍼 테이블 개념이 있지만, 이것은 상속관계를 구현하는 방법 중 하나로 사용된다.
- 논리 모델을 구현 모델(DB설계)로 구현한다.
- 반대로 객체 입장에서의 설계는 동일(논리모델)하지만 그것의 구현만 차이를 가진다. JPA나 자바 입장에서는 반대로 모든 방식을 지원한다.
상속관계 구현의 전략
- 조인전략 : 슈퍼 테이블과 자식 테이블을 각각 구현한다.
- 단일테이블 전략 : 부모와 자식들의 필드를 모두 한 테이블로 한다.
- 서브타입 테이블로 변환 : 각각의 자식테이블이 부모의 필드를 가진다.
조인 전략
- JPA와 가장 유사한 모델
- 자식의 PK는 부모의 FK이기도 하다.
- 부모 클래스에 대한 조회가 많을 때 장점이 크다. 이 경우 단순하고 깔끔한 코딩이 가능하다. 저장공간을 효율적으로 사용하고 메모리를 적게 쓴다.
- 다만, 조회할 때 조인을 자주 사용한다. insert 쿼리가 두 번 발생한다. 테이블이 많아서 관리가 다소 복잡하다.
-
JPA의 기본적인 전략으로 생각하고 사용한다.
- 아래의 코드 중 Inheritance, DiscriminatorColumn, DiscriminatorValue 을 살펴봐야 한다. Inheritance 어너테이션의 전략의 변경만으로 테이블이 자동으로 변경 및 생성된다. 매우 간편하다.
- DiscriminatorColumn으로 부모 테이블에 해당 자식 테이블이 무엇인지를 명시한다. 기본적으로 칼럼명은 Dtype이며 해당 값은 객체명이나 자식객체의 DiscriminatorValue으로 자유롭게 변경 가능하다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
@Setter
@Getter
public abstract 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 Book extends Item {
private String isbn;
private String author;
}
@Entity
@DiscriminatorValue("MOV")
@Setter
@Getter
public class Movie extends Item{
private String direction;
private String actor;
}
단일테이블 전략
- jpa의 기본 전략
- 조인이 필요 없으며 조회가 빠르다.
- 쿼리가 단순하다.
- 다만, 자식 객체과 관련하지 않는 다른 자식 칼럼의 경우 null을 허용해야 한다.
- 단일 테이블에 저장하므로 상황에 따라 조회 성능이 느려진다. 그러나 그런 경우는 크게 없다.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) // 기본값, 싱글 테이블 전략
//@DiscriminatorColumn // 생략하더라도 자동적으로 Dtype 칼럼이 생성된다.
@Setter
@Getter
public abstract class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
}
서브클래스 전략
- 서브클래스간 묶을 수 있는 방법이 없다.
- 이로 인하여 union all을 사용해야 하고, 테이블을 통합적으로 사용하기 어렵다. 시스템 변경도 매우 어렵다. 사실상 사용하지 않는다.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) // 기본값, 싱글 테이블 전략
@Setter
@Getter
public abstract class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
}
final Item item = em.find(Item.class, movie.getId()); // union all
정리
- 조인테이블을 기본으로 가져 간다. 필요 시 단일테이블전략을 사용할 수 있다.
- 단순하고 확장 가능성이 많지 않다고 보일 경우 단일테이블전략을 사용한다.