자바 ORM 표준 JPA 프로그래밍 공부 기록
관계형 데이터베이스에는 상속이라는 개념이 없다.
대신에 슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 가장 유사하다.
💡 즉 상속 관계 매핑은 객체의 상속과 구조와 DB의 슈퍼타입 서브타입 관계를 매핑하는 것
이다.
엔티티 각각을 모두 테이블로 만들고 자식 테이블이 부모 테이블의 기본 키를 받아서 기본 키 + 외래 키로 사용하는 전략이다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
}
@Inheritance(strategy = InheritanceType.JOINED)
상속 매핑은 부모 클래스에 @Inheritance
을 사용해야 한다. 여기에 매핑 전략을 설정해야 하는데, 조인 전략을 사용하므로 InheritanceType.JOINED
을 사용했다.
@DiscriminatorColumn(name="DTYPE")
부모 클래스에 구분 컬럼을 지정한다. 이 컬럼으로 저장된 자식 테이블을 구분할 수 있다. 기본값이 DTYPE이다.
테이블을 하나만 사용한다. 그리고 구분컬럼(DTYPE
)으로 어떤 자식 데이터가 저장되었는지 구분한다. 조인을 사용하지 않으므로 조회 시 제일 빠르다.
주의점은 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다는 것이다. 또한 테이블 하나에 모든 것을 통합하므로 DTYPE
을 필수로 사용해야 한다.
@DiscriminatorColumn
꼭 설정!!!@DiscriminatorColumn
을 지정하지 않으면 기본으로 엔티티 이름 사용자식 엔티티마다 테이블을 만든다.
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
을 선택하면 구현 클래스마다 테이블 전략을 사용한다. 이는 자식 엔티티마다 테이블을 만든다. 일반적으로는 추천 X
부모 클래스는 테이블과 매핑하지 않고, 부모 클래스를 상속받는 자식 클래스에게 매핑 정보만 제공하고 싶을 때 @MappedSuperClass
를 사용
추상 클래스와 비슷한데 @Entity
는 실제 테이블과 매핑 되지만 @MappedSuperClass
는 실제 테이블과는 매핑되지 않는다.
ex) BaseEntity
객체들이 주로 사용하는 공통 매핑 정보를 정의
테이블과 매핑할 필요가 없고 자식 엔티티에게 공통으로 사용되는 매핑 정보만 제공하면 되므로 @MappedSuperClass
를 사용
@MappedSuperclass
public abstract class BaseEntity {
@Id @GeneratedValue
private Long id;
private String name;
private String createdBy;
}
Entity
의 매핑 정보를 상속하기 위해 사용Entity
가 아니므로 em.find()
나 JPQL
에서는 당연히 사용 불가능함@Entity
클래스는 Entity
나 @MappedSuperclass
로 지정한 클래스만 상속 가능
1. 상품의 종류는 음반, 도서, 영화가 있고 이후 더 확장될 수 있다. (상속)
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
public abstract class Item {
@Id
@GeneratedValue
@Column(name="ITEM_ID")
private Long id;
private String name;
...
}
상속 관계 매핑하기 위해 Item (부모클래스)에 @Inheritance
사용하고 속성에 InheritanceType.SINGLE_TABLE
을 선택해서 단일 테이블 전략 사용
단일 테이블 전략은 구분컬럼을 필수로 사용해야 하므로 @DiscriminatorColumn
으로 구분 컬럼 정의하였다.
@Entity
public class Book extends Item{
private String author;
private String isbn;
@MappedSuperclass
public abstract class BaseEntity {
private String createdBy;
private LocalDateTime createdDate;
private String lastModifiedBy;
private LocalDateTime lastModifiedDate;
....
모든 데이터는 등록일과 수정일을 가져야한다. 이를 모든 엔티티에 하나하나 추가 시키는 것 보다는 @MapperSuperclass
를 사용하여 각 클래스에 상속시키는 것이 효율적이다.