조인 전략
엔티티 각각을 모두 테이블로 만들고 자식 테이블이 부모 테이블의 기본키를 받아서 기본키 + 외래키로 사용하는 전략이다.
예시
Item.java (부모 테이블)
package com.book.jpa.chapter07.JoinedStrategy.joined;
import javax.persistence.*;
@Entity
@Inheritance(strategy = InheritanceType.JOINED) // 상속 매핑은 부모 클래스에 해당 어노테이션을 써야한다. 매핑전략 지정
@DiscriminatorColumn(name = "DTYPE") // 부모 클래스에 구분 컬럼을 지정한다. 이 컬럼으로 저장된 자식 테이블을 구분한다.
public abstract class Item {
@Id
@GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
private String name;
private int price;
}
Album.java (자식 테이블)
package com.book.jpa.chapter07.JoinedStrategy.joined;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue("A") // 구분 컬럼에 저장될 값을 지정한다.
public class Album extends Item {
/*
create table album (
artist varchar(255),
item_id int8 not null,
primary key (item_id)
)
*/
private String artist;
}
Book.java (자식 테이블)
package com.book.jpa.chapter07.JoinedStrategy.joined;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
@Entity
@DiscriminatorValue("B")
@PrimaryKeyJoinColumn(name = "BOOK_ID") // ID 재정의
public class Book extends Item {
private String author;
private String isbm;
}
Movie.java (자식 테이블)
package com.book.jpa.chapter07.JoinedStrategy.joined;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue("M")
public class Movie extends Item {
/*
create table movie (
actor varchar(255),
director varchar(255),
item_id int8 not null,
primary key (item_id)
)
*/
private String director;
private String actor;
}
테이블 생성 쿼리
create table item (
dtype varchar(31) not null,
item_id int8 not null,
name varchar(255),
price int4 not null,
primary key (item_id)
)
create table movie (
actor varchar(255),
director varchar(255),
item_id int8 not null,
primary key (item_id)
)
create table book (
author varchar(255),
isbm varchar(255),
book_id int8 not null,
primary key (book_id)
)
create table album (
artist varchar(255),
item_id int8 not null,
primary key (item_id)
)
특징
1) 조회할때 조인을 자주 사용한다.
2) 객체를 타입으로 구분할 수 있지만 테이블은 타입의 개념이 없으므로, 타입을 구분하는 컬럼이 필요하다.
장점
1) 테이블이 정규화된다.
2) 외래키 참조 무결성 제약조건을 활용할 수 있다.
3) 저장 공간을 효율적으로 사용한다.
단점
1) 조회할때 조인이 많이 사용되므로 성능이 저하된다.
2) 조회 쿼리가 복잡하다.
3) 데이터를 등록할 INSERT 쿼리가 2번 실행된다.
단일 테이블 전략
테이블을 하나만 사용하고, 구분 컬럼으로 어떤 자식 데이터가 저장되었는지 구분한다. 조인을 사용하지 않으므로 가장 빠르다.
예시
Item.java (부모 테이블)
package com.book.jpa.chapter07.JoinedStrategy.single;
import javax.persistence.*;
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DTYPE") // 부모 클래스에 구분 컬럼을 지정한다. 이 컬럼으로 저장된 자식 테이블을 구분한다.
public abstract class SingleItem {
@Id
@GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
private String name;
private int price;
}
Album.java (자식 테이블)
package com.book.jpa.chapter07.JoinedStrategy.single;
import com.book.jpa.chapter07.JoinedStrategy.joined.Item;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue("A") // 구분 컬럼에 저장될 값을 지정한다.
public class SingleAlbum extends SingleItem {
private String artist;
}
Book.java (자식 테이블)
package com.book.jpa.chapter07.JoinedStrategy.single;
import com.book.jpa.chapter07.JoinedStrategy.joined.Item;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
@Entity
@DiscriminatorValue("B")
public class SingleBook extends SingleItem {
private String author;
private String isbm;
}
Movie.java (자식 테이블)
package com.book.jpa.chapter07.JoinedStrategy.single;
import com.book.jpa.chapter07.JoinedStrategy.joined.Item;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue("M")
public class SingleMovie extends SingleItem {
private String director;
private String actor;
}
테이블 생성 쿼리
create table single_item (
dtype varchar(31) not null,
item_id int8 not null,
name varchar(255),
price int4 not null,
artist varchar(255),
author varchar(255),
isbm varchar(255),
actor varchar(255),
director varchar(255),
primary key (item_id)
)
특징
1) 구분 컬럼을 꼭 사용해야한다. @DiscriminatorColumn 을 꼭 설정해야한다.
2) @DiscriminatorValue 를 지정하지 않으면 기본으로 엔티티 이름을 사용한다 (Movie, Album 등)
장점
1) 조인이 필요 없으므로 일반적으로 조회 성능이 빠르다
2) 조회 쿼리가 단순하다
단점
1) 자식 엔티티가 매핑한 컬럼은 모두 null 을 허용해야한다
2) 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다. 상황에 따라서 조회 성능이 오히려 느려질 수 있다.
구현 클래스별 테이블 전략
자식 엔티티마다 테이블을 만든다. 그리고 자식 테이블을 각각에 필요한 컬럼이 모두 있다.
예시
Item.java (부모 테이블)
package com.book.jpa.chapter07.JoinedStrategy.table_per;
import javax.persistence.*;
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@DiscriminatorColumn(name = "DTYPE") // 부모 클래스에 구분 컬럼을 지정한다. 이 컬럼으로 저장된 자식 테이블을 구분한다.
public abstract class PerItem {
/*
테이블 생성 쿼리 없음
*/
@Id
@GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
private String name;
private int price;
}
Album.java (자식 테이블)
package com.book.jpa.chapter07.JoinedStrategy.table_per;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue("A") // 구분 컬럼에 저장될 값을 지정한다.
public class PerAlbum extends PerItem {
private String artist;
}
Book.java (자식 테이블)
package com.book.jpa.chapter07.JoinedStrategy.table_per;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
@Entity
@DiscriminatorValue("B")
public class PerBook extends PerItem {
private String author;
private String isbm;
}
Movie.java (자식 테이블)
package com.book.jpa.chapter07.JoinedStrategy.table_per;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue("M")
public class PerMovie extends PerItem {
private String director;
private String actor;
}
테이블 생성 쿼리
create table per_album (
item_id int8 not null,
name varchar(255),
price int4 not null,
artist varchar(255),
primary key (item_id)
)
create table per_book (
item_id int8 not null,
name varchar(255),
price int4 not null,
author varchar(255),
isbm varchar(255),
primary key (item_id)
)
create table per_movie (
item_id int8 not null,
name varchar(255),
price int4 not null,
actor varchar(255),
director varchar(255),
primary key (item_id)
)
장점
1) 서브 타입을 구분해서 처리할때 효과적이다.
2) not null 제약조건을 사용할 수 있다.
단점
1) 여러자식 테이블을 함께 조회할때 성능이 느리다. (SQL에 UNION을 사용해야한다)
2) 자식 테이블을 통합해서 쿼리하기 어렵다.
특징
1) 구분 컬럼을 사용하지 않는다.
교재 참고: 자바 ORM 표준 JPA 프로그래밍
'Coding > JPA' 카테고리의 다른 글
[JPA] JQPL 사용해서 페이징 수행 (0) | 2022.02.24 |
---|---|
[JPA] 복합키 - 비식별관계 매핑하기 (@IdClass, @EmbeddedId) (0) | 2022.02.09 |
JPA 중복 컬럼 상속으로 생성하는 방법 (0) | 2022.01.16 |
[SpringBoot JPA] Paging 페이징 (0) | 2021.10.26 |
[SpringBoot JPA] Limit, Order 처리하기 (0) | 2021.10.26 |