자바 ORM 표준 JPA 프로그래밍 : 교보문고
자바 ORM 표준 JPA 프로그래밍 - 기본편 : 인프런
객체에는 상속이라는 개념이 존재한다. 하지만 RDB 에서 상속이라는 개념은 존재하지 않는다.
때문에 객체와 테이블간 패러다임문제가 발생한다. 하지만 RDB에서는 객체 상속과 비슷한 모델인 Super, Sub 타입이 존재한다. 이 논리 모델을 물리적 모델로 구현하기 위한 방법을 JPA 에서 지원해 주고 있다.
JPA 에서 지원해주는 상속 전략 중 하나로 상위 테이블과 하위 테이블을 생성한다.
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 (
DTYPE varchar(31) not null,
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)
)
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public class Item
{
@Id @GeneratedValue
private Long id;
무결성 제약 조건에 대한 부하 적음
SCHEME
가 간결해진다.1. Sub 객체 Insert 시 Insert 쿼리가 2개 발생한다.
상위 클래스 Item 이 먼저 Insert 와 하위 클래스 Movie 가 같이 Insert 되고 있다.
2. 하위 객체 조회 시 JOIN Query 발생
Movie findMovie = em.find(Movie.class, movie.getId());
System.out.println("find Movie : "+findMovie.getActor());
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_3_0_,
movie0_.director as director2_3_0_
from
Movie movie0_
inner join
Item movie0_1_
on movie0_.id=movie0_1_.id
where
movie0_.id=?
find Movie : one
테이블 구조가 복잡해지면 복잡한 JOIN Query 가 생성된다. 이로인한 성능저하 또한 발생할 수 있다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public class Item
{
@Id @GeneratedValue
private Long id;
private String name;
private int price;
상위 객체에서
@Inheritance
와 함께 선언되는 Annotation 이며
상위 객체 테이블에서 구분을 위한 컬럼이 생성된다.
기본값이DTYPE
인 컬럼이 상위 객체 테이블에 생성되고
해당 컬럼의 값은 설정하지 않으면Entity
명이 들어간다.
하위 객체에 @DiscriminatorValue
를 사용하면 사용자가 값을 직접 정의할 수 있다.
@Entity
@DiscriminatorValue("M")
public class Movie extends Item
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Item
{
상위 객체의 클래스에 모든 하위 객체의 필드들을 넣는 전략
Hibernate:
create table Item (
DTYPE varchar(31) not null,
id bigint not null,
name varchar(255),
price integer not null,
author varchar(255),
isbn varchar(255),
actor varchar(255),
director varchar(255),
artist varchar(255),
primary key (id)
)
@DiscriminatorColumn 을 추가적으로 선언하지 않아도
DTYPE 이 자동으로 생성된다.
--
상위 객체의 테이블을 생성하지 않고 하위 객체에 대한 테이블만 생성
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Item
{
Hibernate: create sequence hibernate_sequence start with 1 increment by 1
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 JOIN 발생
)Item findMovie = em.find(Item.class, movie.getId());
System.out.println("find Movie : "+findMovie.getName());
Hibernate:
select
item0_.id as id1_2_0_,
item0_.name as name2_2_0_,
item0_.price as price3_2_0_,
item0_.author as author1_1_0_,
item0_.isbn as isbn2_1_0_,
item0_.actor as actor1_3_0_,
item0_.director as director2_3_0_,
item0_.artist as artist1_0_0_,
item0_.clazz_ as clazz_0_
from
( select
id,
name,
price,
author,
isbn,
null as actor,
null as director,
null as artist,
1 as clazz_
from
Book
union
all select
id,
name,
price,
null as author,
null as isbn,
actor,
director,
null as artist,
2 as clazz_
from
Movie
union
all select
id,
name,
price,
null as author,
null as isbn,
null as actor,
null as director,
artist,
3 as clazz_
from
Album
) item0_
where
item0_.id=?
find Movie : one
@Inheritance
를 통해 객체의 상속을 테이블에서 구현할 수 있고
전략에 따라 구조변경이 쉽다!