JPA 연관 관계 - 상속 관계 Mapping

목차

JPA 상속 관계 Mapping

  • 관계형 데이터 베이스는 상속 관계가 없다.
  • 슈펴타입 서브타입 관계라는 모델링 기법이 객체의 상속과 유사하다.
  • 상속관계 Mapping : 객체의 상속 관계와 DB 의 슈퍼타입 서브타입 관계를 Mapping

슈퍼타입 서브타입 논리 모델을 객체의 상속관계를 물리 모델로 구현하는 방법

객체의 상속관계를 슈퍼타입 서브타입 모델로 구현하는 방법은 3가지 방법이 있다.

전략 설명
조인 전략 각각 테이블로 변환 (연관 관계로 관리)
단일 테이블 전략 통합 테이블로 변환 (하나의 테이블로 관리)
구현 클래스마다 테이블 전략 서브타입 테이블로 변환

사용하는 어노테이션

  • @Inheritance
  • @DiscriminatorColumn(name=”DTYPE”)
  • @DiscriminotorValue

@Inheritance 전략

strategy 설명
InheritanceType.JOINED 조인 전략
InheritanceType.SINGLE_TABLE 단일 테이블 전략
InheritanceType.TABLE_PER_CLASS 구현 클래스마다 테이블 전략
@Entity
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 Book extends Item{
private String author;
private String isbn;
}
@Entity
public class Movie extends Item{
private String director;
private String actor;
}

1. 조인 전략

@Inheritance(strategy = InheritanceType.JOINED)

Hibernate: create table Album (artist varchar(255), id bigint not null, primary key (id))
Hibernate: create table Book (author varchar(255), isbn varchar(255), id bigint not null, primary key (id))
Hibernate: create table Item (id bigint not null, name varchar(255), price integer not null, primary key (id))
Hibernate: create table Movie (actor varchar(255), director varchar(255), id bigint not null, primary key (id))

Hibernate: alter table Album add constraint FKcve1ph6vw9ihye8rbk26h5jm9 foreign key (id) references Item
Hibernate: alter table Book add constraint FKbwwc3a7ch631uyv1b5o9tvysi foreign key (id) references Item
Hibernate: alter table Movie add constraint FK5sq6d5agrc34ithpdfs0umo9g foreign key (id) references Item
Movie movie = new Movie();
movie.setDirector("aaaa");
movie.setActor("bbbb");
movie.setName("바람과 함께 사라지다.");
movie.setPrice(10000);

em.persist(movie);
em.flush();
em.clear();

em.find(Movie.class, movie.getId());

데이터 삽입

데이터 삽입시 슈퍼타입과 서브타입 각각에 쿼리문에 보내지는 것을 확인할 수 있다.

Hibernate: /* insert hellojpa.Movie */ insert into Item (name, price, id) values (?, ?, ?)
Hibernate: /* insert hellojpa.Movie */ insert into Movie (actor, director, id) values (?, ?, ?)

데이터 조회

데이터 조회시 슈퍼타입과 서브타입을 조인해서 가져오는 것을 확인할 수 있다.

Hibernate: select movie0_.id as id1_2_0_, movie0_1_.name as name2_2_0_, movie0_1_.price as price3_2_0_, movie0_.actor as actor1_4_0_, movie0_.director as director2_4_0_ from Movie movie0_ inner join Item movie0_1_ on movie0_.id=movie0_1_.id where movie0_.id=?

DTYPE 이 있을 경우

DTYPE 이 없을 경우

  • @DiscriminatorColumn 를 이용해 DTYPE 을 명시해 줄 수 있다.
  • DTYPE 값은 @DiscriminotorValue 를 이용해 명시해 줄 수 있다. 기본값은 Entity Class 명이다.
  • 어떤 객체에 맞춰서 슈퍼타입 데이터 가 들어왔는지 명확하게 알 수 있다.

2. 단일 테이블 전략 - JPA 기본 전략

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)

  • 한 테이블에 모든 데이터가 들어가 관리되는 방식
  • 한 테이블에 관리하기 때문에 DTYPE 이 자동적으로 생성된다.
Hibernate: create table Item (
DTYPE varchar(31) not null,
id bigint generated by default as identity,
name varchar(255),
price integer not null,
artist varchar(255),
author varchar(255),
isbn varchar(255),
actor varchar(255),
director varchar(255),
primary key (id)
)
Hibernate: /* insert hellojpa.Movie */ insert into Item (id, name, price, actor, director, DTYPE) values (null, ?, ?, ?, ?, 'Movie')

Hibernate: select movie0_.id as id2_0_0_,
movie0_.name as name3_0_0_,
movie0_.price as price4_0_0_,
movie0_.actor as actor8_0_0_,
movie0_.director as director9_0_0_
from Item movie0_
where movie0_.id=?
and movie0_.DTYPE='Movie'

3. 구현 클래스마다 테이블 전략

  • Item Table 생성 쿼리가 별도로 실행되지 않는 것을 확인할 수 있다.
Hibernate: create table Album (id bigint not null, name varchar(255), price integer not null, artist varchar(255), primary key (id))
Hibernate: create table Book (id bigint not null, name varchar(255), price integer not null, author varchar(255), isbn varchar(255), primary key (id))
Hibernate: create table Movie (id bigint not null, name varchar(255), price integer not null, actor varchar(255), director varchar(255), primary key (id))
  • 구현 테이블 마다 테이블 전략은 상위 타입으로 데이터 조회시 문제가 발생한다.
  • 서브 타입 테이블을 전부 UNION 해서 조회 조건에 맞는 데이터가 있는지 확인한 후 가져온다.
Hibernate: 
select item0_.id as id1_2_0_, item0_.name as name2_2_0_, item0_.price as price3_2_0_,
item0_.artist as artist1_0_0_, item0_.author as author1_1_0_, item0_.isbn as isbn2_1_0_,
item0_.actor as actor1_4_0_, item0_.director as director2_4_0_, item0_.clazz_ as clazz_0_
from (
select id, name, price, artist, null as author, null as isbn, null as actor, null as director, 1 as clazz_ from Album
union all
select id, name, price, null as artist, author, isbn, null as actor, null as director, 2 as clazz_ from Book
union all
select id, name, price, null as artist, null as author, null as isbn, actor, director, 3 as clazz_ from Movie
) item0_ where item0_.id=?
Share