반응형
상속관계 매핑이란?
객체는 상속관계가 존재하지만 관계형 데이터베이스에는 존재하지 않는 개념이다.
객체의 상속관계를 관계형 데이터베이스의 슈퍼타입/서브타입 관계를 매핑하는것..!
그렇다면 논리 모델을 물리 모델로 어떻게 구현할 수 있을까?
JPA 입장에서는 간단하게 매핑전략만 선택하면 DB입장에서 봤을때 3가지 방식으로 구현할 수 있다.
- @Inheritance(strategy=InheritanceType.전략)
-> default 전략은 SINGLE_TABLE(단일테이블 전략)이다.
-> 전략종류 :
1). SINGLE_TABLE : 단일테이블에 한번에 모든 정보를 다 담는 전략.
위의 사진에 따르면 ALBUM / MOVIE / BOOK 별도의 테이블에 데이터를 저장한다.
2). JOINED : 각각의 테이블별로 정규화된 방법.
3). TABLE_PER_CLASS : 엔티티 별로 각 테이블별로 분리하여 담는다. - @DiscriminatorColumn(name="DTYPE")
-> 부모클래스에 선언하며, 하위클래스를 구분하는 용도의 컬럼을 만든다. default = DTYPE - @DiscriminatorValue("밸류")
-> 하위 클래스에 선언하며, 슈퍼타입의 구분컬럼에 저장할 값을 지정하여 사용한다.
-> 어노테이션을 사용하지 않으면 기본값으로 클래스이름이 설정된다.
한번 각각의 전략을 어떻게 사용하는지 코드로 알아보자.
공통된 자식 Entity를 먼저 구현하고 보자.
[자식-1]
@Entity
public class Album extends Item {
private String artist;
}
[자식-2]
@Entity
public class Movie extends Item {
private String director;
private String actor;
}
[자식-3]
@Entity
public class Book extends Item {
private String author;
private String isbn;
}
[SINGLE_TABLE 전략]
한테이블에 다 때려넣는 전략 -> 정규화를 안해서 빠르긴 하지만 불필요한 공간도 많이 사용할 수 있다. 상황에 맞게 쓰자. 테이블에 모든 컬럼을 저장하기 때문에, DTYPE 없이는 테이블을 판단할 수 없음을 유의하자.
[부모]
@Entity
@DiscriminatorColumn
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int price;
}
쿼리를 확인해 보자
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)
)
장단점을 확인해보자
- 장점
- 조인이 필요 없으므로 일반적인 조회 성능이 빠르다.
- 조회 쿼리가 단순핟.
- 단점
- 자식 엔티티가 매핑한 컬럼은 모두 NULL을 허용해야 한다.
- 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다.
- 상황에 따라서 조인 전략보다 성능이 오히려 느려질 수 있다.
[JOINED 전략]
-> 각각 테이블로 만들어진다.
[부모]
@Entity
@Inheritance(strategy = InheritanceType.전략)
@DiscriminatorColumn
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int price;
}
실행 쿼리를 한번 보자!
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 generated by default as identity,
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 FKcwer2ph22we3ye8rbk26h5jm9
foreign key (id)
references Item
Hibernate:
alter table Book
add constraint FK32ksjioef2w80wjw3ijr282ji
foreign key (id)
references Item
Hibernate:
alter table Movie
add constraint FK792jkwehjrkwe792931hjew6s
foreign key (id)
references Item
테이블이 하나씩 생성되는것을 볼수있다.
장단점도 확인해보자.
- 장점
- 테이블이 정규화가 잘되어있다.
- 외래 키 참조 무결성 제약조건 활용 가능
- ITEM의 PK가 ALBUM, MOVIE, BOOK의 PK이자 FK이다. 그래서 다른 테이블에서 아이템 테이블만 바라보도록 설계하는 것이 가능 하다
- 단점
- 조회시 조인을 많이 사용한다. 단일 테이블 전략에 비하면 성능이 안나온다. 조인하니까.
- 데이터 저장시에 INSERT 쿼리가 상위, 하위 테이블 두번 발생한다.
- 정리
- 오히려 저장공간이 효율화 되기 때문에 장점이 크다.
[TABLE_PER_CLASS 전략]
Join전략과 비슷하지만 부모Entity의 컬럼들을 자식엔티티로 넘겨버린다.
즉 name,price 컬럼들이 중복되어 생성된다.
부모 Entity는 실제로 생성되는 테이블이 아니므로, 무조건 abstract 클래스여야하고, @DiscriminatorColumn도 필요없어진다.
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Item {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private int price;
}
쿼리를 확인해보자
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)
)
세개의 테이블만 생성되는것을 확인할 수 있다.
- 장점
- 서브 타입을 명확하게 구분해서 처리할 때 효과적이다
- NOT NULL 제약조건을 사용할 수 있다.
- 단점
- 여러 자식 테이블을 함께 조회할 때 성능이 느리다(UNION SQL)
- 자식 테이블을 통합해서 쿼리하기 어렵다.
- 변경이라는 관점으로 접근할 때 굉장히 좋지 않다.
잘사용하지 않는 전략이라고 보면 될것같다.
반응형
'JPA' 카테고리의 다른 글
[JPA] Fetch Join 이란? N+1 이란? fetch join을 사용하는 이유 (0) | 2021.08.23 |
---|---|
[JPA] @Embedded @Embeddable 이란? 예제 (0) | 2021.08.17 |
[JPA] No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer 오류 (0) | 2021.08.11 |
[JPA] 관계 매핑 기초 정리 (0) | 2021.07.23 |
[JPA] SpringBoot + JPA @EnableJpaAuditing 이란? (0) | 2021.07.23 |