Album, Book, Item, Movie를 등록해주고
Album
package hellojpa;
import javax.persistence.Entity;
@Entity
public class Album extends Item{
private String artist;
}
Book
package hellojpa;
import javax.persistence.Entity;
@Entity
public class Book extends Item{
private String author;
private String isbn;
}
Item
package hellojpa;
import javax.persistence.*;
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Item {
@Id
@GeneratedValue
private Long id;
private String name;
private int price;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
Movie
package hellojpa;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
@Entity
public class Movie extends Item{
private String director;
private String actor;
public String getDirector() {
return director;
}
public void setDirector(String director) {
this.director = director;
}
public String getActor() {
return actor;
}
public void setActor(String actor) {
this.actor = actor;
}
}
JpaMain
package hellojpa;
import javax.management.relation.Role;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Movie movie = new Movie();
movie.setDirector("aaaa");
movie.setActor("bbbb");
movie.setName("바람과함께사라지다");
movie.setPrice(10000);
em.persist(movie);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
Hibernate:
call next value for hibernate_sequence
Hibernate:
/* insert hellojpa.Movie
*/ insert
into
Item
(name, price, id)
values
(?, ?, ?)
Hibernate:
/* insert hellojpa.Movie
*/ insert
into
Movie
(actor, director, id)
values
(?, ?, ?)
조회를 해보면
try {
Movie movie = new Movie();
movie.setDirector("aaaa");
movie.setActor("bbbb");
movie.setName("바람과함께사라지다");
movie.setPrice(10000);
em.persist(movie);
em.flush();
em.clear();
Movie findMovie = em.find(Movie.class, movie.getId());
System.out.println("findMovie = " + findMovie);
tx.commit();
join이 필요할 때 join을 해주게 된다.(item과 movie)
Hibernate:
call next value for hibernate_sequence
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_6_0_,
movie0_.director as director2_6_0_
from
Movie movie0_
inner join
Item movie0_1_
on movie0_.id=movie0_1_.id
where
movie0_.id=?
findMovie = hellojpa.Movie@2f860823
Item 테이블에 어노테이션을 넣어주면 Item 부분에 Dtype 이 생긴다.
DiscriminatorColumn
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public class Item {
그리고 Movie 부분에 DiscriminatorValue("M")을 넣어줘서 구분해줄 수도 있다.
@Entity
@DiscriminatorValue("M")
public class Movie extends Item{
단일테이블 전력으로 바꾸려면 이렇게 해주자.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
public class Item {
insert와 join을 할 필요가 없다.
Hibernate:
call next value for hibernate_sequence
Hibernate:
/* insert hellojpa.Movie
*/ insert
into
Item
(name, price, actor, director, DTYPE, id)
values
(?, ?, ?, ?, 'M', ?)
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='M'
findMovie = hellojpa.Movie@a619c2
그리고 join 전략이 아닌 이 단일테이블 전략에서
@DiscriminatorColumn이 없어도 Dtype이 생기게 된다.
@DiscriminatorColumn
Hibernate:
create table Item (
DTYPE varchar(31) not null,
id bigint not null,
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)
)
결론 적으로는 쿼리 한번 조회 한번이 생기게 된다.
package hellojpa;
import javax.management.relation.Role;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Movie movie = new Movie();
movie.setDirector("aaaa");
movie.setActor("bbbb");
movie.setName("바람과함께사라지다");
movie.setPrice(10000);
em.persist(movie);
em.flush();
em.clear();
Movie findMovie = em.find(Movie.class, movie.getId());
System.out.println("findMovie = " + findMovie);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
Hibernate:
call next value for hibernate_sequence
Hibernate:
/* insert hellojpa.Movie
*/ insert
into
Item
(name, price, actor, director, DTYPE, id)
values
(?, ?, ?, ?, 'M', ?)
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='M'
findMovie = hellojpa.Movie@bcb09a6
구현 클래스마다 테이블 전략을 보자.(실무에서 쓰면 안됨,)
Item을 추상클래스로 만들어주면 create에 item이 없다.
package hellojpa;
import javax.persistence.*;
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@DiscriminatorColumn
public abstract class Item {
@Id
@GeneratedValue
private Long id;
private String name;
private int price;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
조인 전략을 살펴보자.
장점으로
- 테이블 정규화
- 외래 키 참조 무결성 제약조건 활용가능
- 저장공간 효율화
단점으로
- 조회시 조인을 많이 사용, 성능 저하
- 조회 쿼리가 복잡
- 데이터 저장시 INSERT SQL 2번 호출
단일 테이블 전략도 보자.
장점으로
- 조인이 필요 없으므로 일반적으로 조회 성능이 빠르다.
- 조회 쿼리가 단순함
단점으로
- 자식 엔티티가 매핑한 컬럼은 모두 null 허용되고
- 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있고 상황에 따라 조회 성능이 느려질 수 있다.
구현 클래스마다 테이블 전략으로
- 일단 쓰면 안되는 전략이고
장점으로는
- 서브 타입을 명확하게 구분해서 처리할 때 효과적이고
- not null 제약조건 사용 가능
단점으로
- 여러 자식 테이블을 함께 조회할 때 성능이 느리다.(UNION SQL)
- 자식 테이블을 통합해 쿼리하기 어렵다.
JPA에서의 주요 어노테이션을 보자.
- Inheritance(strategy = InheritanceType.XXX)
- JOINED: 조인 전략
- SINGLE_TABLE: 단일 테이블 전략
- TABLE_PER_CLASS: 구현 클래스마다 테이블 전략
- @DiscriminatorColumn(name="DTYPE")
- @DiscriminatorValue("XXX")
<출처 김영한: 자바 ORM 표준 JPA 프로그래밍 - 기본편 >
https://www.inflearn.com/course/ORM-JPA-Basic/dashboard
자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의
JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., - 강의 소개 | 인프런
www.inflearn.com
'Spring > JPA' 카테고리의 다른 글
Mapped Superclass - 매핑 정보 상속 / 상속관계 매핑 (0) | 2022.05.28 |
---|---|
실전 예제 3 - 다양한 연관관계 매핑 (0) | 2022.05.25 |
일대일 1:1 / 다대다 N:M (0) | 2022.05.25 |
다대일 N:1 / 일대다 1:N (0) | 2022.05.25 |
예제 - 연관관계 매핑 시작 (0) | 2022.05.25 |