목차
객체의 상속관계
extends로 지원해준다.
@Entity
public class Item {
@Id @GeneratedValue
@Column(name = "item_id")
private Long id;
private String name;
private int price;
private int stockQuantity;
}
@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 String isbn;
}
DB에서 슈퍼타입-서브타입 모델을 구현하는 방법
관계형 데이터베이스는 상속관계가 없지만
상속과 유사한 슈퍼타입-서브타입 모델링 기법이 있다.
JPA에서는 아래 3가지를 모두 지원해주며, @Inheritance 어노테이션으로 표현할 수 있다.
1. 통합 테이블로 만들어 조인없이 결과를 얻어오는 방법
장점 : 조인이 없어서 조회 성능이 빠르다.
단점 : 자식 엔티티가 매핑한 컬럼은 모두 null이 허용된다.
테이블이 너무 커질 수 있다. 상황에 따라서는 조회 성능이 오히려 느려질 수 있다.
JPA에서 기본전략이다. Item 엔티티에 @Entity만 사용하거나
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 로 지정한 경우에 통합 테이블로 만들어준다.
2. 각각의 테이블로 나누되 테이블마다 컬럼을 중복하는 방법
장점 : 통합 테이블보다 테이블이 나뉘어져 컬럼에 not null제약조건을 사용할 수 있다.
단점 : 객체지향에서는 Item으로 Album, Book, Movie를 조회할 수 있다.
하지만 각 테이블마다 나뉘어진 상태에서 Item으로 조회하게되면
모든 테이블을 조회해서 결과를 가져와야한다(Union SQL필요)
=> DB설계자, ORM 전문가 모두 추천하지 않는 방법이다!!
Item엔티티에 @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)로 지정해준다.
객체에서는 Item엔티티에 abstract 키워드를 붙여서 추상클래스로 만들어준다.
그러면 extends를 사용하면서, Item테이블은 생성되지 않는다.
3. 각각의 테이블로 나누되 중복 컬럼은 공통 테이블로 분리하고 조인으로 결과를 얻어오는 방법
장점 : 정규화를 통해 저장공간이 효율화된다.
단점 : 조회 시 조인을 많이 사용하게되어 성능이 저하될 수 있다.
데이터 저장 시 Insert문을 2번 호출한다.
Item엔티티에 @Inheritance(strategy = InheritanceType.JOINED)로 지정해준다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Item {
@Id @GeneratedValue
@Column(name = "item_id")
private Long id;
private String name;
private int price;
private int stockQuantity;
}
@Entity
public class Movie extends Item{
private String director;
private String actor;
}
Movie movie = new Movie();
movie.setName("아바타");
movie.setPrice(10000);
movie.setStockQuantity(10);
movie.setActor("배우");
movie.setDirector("작가");
em.persist(movie);
@DiscriminatorColumn
데이터베이스 테이블을 조회했을 때, item에 입력된 값이 자식인 album, book, movie 중 어떤 것에 의해 작성되었는지를 표시해주는 컬럼을 추가해준다.
부모 테이블에 설정한다.
@DiscriminatorColumn을 설정했을 때 생기는 컬럼의 기본명은 DTYPE으로, (name = "~")으로 컬럼명을 변경할 수 있다.
DTYPE에 들어가는 기본값은 엔티티명이다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public class Item {
@Id @GeneratedValue
@Column(name = "item_id")
private Long id;
private String name;
private int price;
private int stockQuantity;
}
@Entity
public class Movie extends Item{
private String director;
private String actor;
}
@DiscriminatorValue
@DiscriminatorColumn에 입력되는 값을 변경할 수 있다.
자식테이블에 설정한다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public class Item {
@Id @GeneratedValue
@Column(name = "item_id")
private Long id;
private String name;
private int price;
private int stockQuantity;
}
@Entity
@DiscriminatorValue("M")
public class Movie extends Item{
private String director;
private String actor;
}
@MappedSuperclass
기본적으로 필요한 createdBy, createTime, updatedBy... 등등 모든 엔티티에서 공통적으로 사용하는 컬럼들의 경우
BaseEntity를 생성한 후 해당 어노테이션을 붙여준다.
주의! @MappedSuperclass는 상속관계 매핑이 아니다.
자식 클래스에 컬럼정보만 제공해주는 것이다.
직접 생성해서 사용할 일이 없으므로 추상 클래스를 권장한다.
@MappedSuperclass
public abstract class BaseEntity {
private String createBy;
@Column(name = "updateBy")
private String update;
}
@Entity
public class Member extends BaseEntity {
@Id @GeneratedValue
@Column(name = "member_id")
private Long id;
private String name;
}
'Backend' 카테고리의 다른 글
[JPA] 값 타입(기본값, @Embedded, 값타입 컬렉션) (0) | 2022.02.22 |
---|---|
[JPA] 프록시와 즉시로딩, 지연로딩 / 영속성 전이와 고아객체 (0) | 2022.02.21 |
[JPA] 다양한 연관관계 매핑(다대일, 일대일, 다대다) (0) | 2022.02.21 |
[JPA]영속성 관리 : 내부 동작 방식 (0) | 2022.02.21 |
[JPA] 연관관계 매핑 (0) | 2022.02.20 |