티스토리 뷰
개념 설명
상속관계 매핑
정리하자면, DB의 슈퍼타입-서브타입 모델링 기법을 3가지 방법 중 어떤 걸 선택하여 구현해도 다 매핑할 수 있도록 JPA가 지원해줌.
주요 어노테이션
도입
단일 테이블 전략 (1)
부모 클래스 Item
@Entity
public abstract class Item {
@Id
@GeneratedValue
private Long id;
private String name;
private int price;
}
Album
@Entity
public class Album extends Item {
private String artist;
}
Book
@Entity
public class Book extends Item {
private String author;
private String isbn;
}
Movie
@Entity
public class Movie extends Item {
private String director;
private String actor;
}
이렇게 하고 실행시켜보면
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)
)
이렇게 한 테이블에 다 떼려박혀 나옴.
조인 전략
Item 클래스에
@Inheritance(strategy = InheritanceType.JOINED)
이걸 추가하고
getter, setter 다 만들어준 후
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
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;
}
}
JPAMain을 통해서
Movie에 값을 넣어준다.
그 전에 Movie에도 getter, setter 추가.
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("김AB");
movie.setActor("한BC");
movie.setName("무빙");
movie.setPrice(10000);
em.persist(movie);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
콘솔 출력 결과는
이제 조회를 해보면.
일단 movie를 가져오려면 item을 조인해 가져와야 한다는 걸 인지하고 있자.
//조회해보기 - 먼저 1차캐시 날리기
em.flush();
em.clear();
Movie findMovie = em.find(Movie.class, movie.getId());
System.out.println("findMovie = "+ findMovie);
콘솔을 보면
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_5_0_,
movie0_.director as director2_5_0_
from
Movie movie0_
inner join
Item movie0_1_
on movie0_.id=movie0_1_.id
where
movie0_.id=?
findMovie = inflearn.exjpa.jpaExample.item.Movie@127705e4
JPA가 이런 것 까지 다 해준다.
조회할 때 Join이 필요하면 Join 해주고,
insert할 때 2번 insert해야 하면 그거까지 jpa가 챙겨서 다 해준다.
이제 Item 클래스에
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public abstract class Item { }
@DiscriminatorColumn 추가하면
Hibernate:
create table Item (
DTYPE varchar(31) not null,
id bigint not null,
name varchar(255),
price integer not null,
primary key (id)
)
DTYPE 들어와 있고,
H2 가보면
추가되어있음.
@DiscriminatorColumn 추가하면
DTYPE 이 생기고
그 안에 엔티티 명이 들어가게 된다.
(@DiscriminatorColumn(name = "~~~") 이렇게 이름을 직접 지정해줄 수도 있다.
사실 안 넣어도 무방하긴 하나, 운영하거나 DB만 딱 쿼리를 확인했을 때는 얘가 뭐 때문에 들어왔는지를 모른다.
그리고 세부사항을 각각 이름 지정해서 넣고 싶다면 사용하는 어노테이션이
@DIscriminatorValue("이름")
@Entity
@DiscriminatorValue("A")
public class Album extends Item { }
@Entity
@DiscriminatorValue("B")
public class Book extends Item { }
@Entity
@DiscriminatorValue("M")
public class Movie extends Item { }
이렇게 들어감을 확인할 수 있음.
조인 전략 개념 정리
조인 전략
장점과 단점
단일 테이블 전략
장점과 단점
단일 테이블 전략 실습
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
public abstract class Item { }
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
이렇게 바꿔놓고 돌리면 된다.
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)
)
다 들어와 있음
Insert 쿼리도 한 번만 나간다.
Hibernate:
/* insert inflearn.exjpa.jpaExample.item.Movie
*/ insert
into
Item
(name, price, actor, director, DTYPE, id)
values
(?, ?, ?, ?, 'M', ?)
select 쿼리도 아주 심플하게 나간다.
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'
Join 필요없다.
장점 : 성능
- 인서트 한 번만 들어가고, 조인 필요 없고, select도 깔끔함.
@DiscriminatorColumn 이게 없어도 DTYPE은 생성된다.
다른 전략은 어떻게든 어떤 테이블에 들어가는지를 확인할 수 있는데,
얘는 한 테이블에 다 때려박기 때문에 JPA가 구분을 위해 DTYPE을 넣어준다 필수 로.
구현 케이스마다 테이블 전략
구현 케이스마다 테이블 전략 실습
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@DiscriminatorColumn
public abstract class Item { //원래 abstract class로 만들었어야 한다.
}
어노테이션을
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
이걸로 바꿔준다.
그러면 Item클래스 따로 생성이 안 된다.
그러면 @DiscriminatorColumn 도 있어도 쓸모가 없다.
값을 뺄 때고 넣을 때는 좋은데,
조회할 때가 문제
JPAMAIN
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("김AB");
movie.setActor("한BC");
movie.setName("무빙");
movie.setPrice(10000);
em.persist(movie);
//조회해보기 - 먼저 1차캐시 날리기
em.flush();
em.clear();
Item findItem = em.find(Item.class, movie.getId());
System.out.println("item = " + findItem);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
Item findItem = em.find(Item.class, movie.getId());
System.out.println("item = " + findItem); 이렇게 찾으려고 하면
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_5_0_,
item0_.director as director2_5_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=?
이렇게 일일이 union 해서 전체에서 다 뒤져야 한다...
강의를 마치며 다시 정리
'[개발] - Spring > JPA 공부' 카테고리의 다른 글
실전 예제 - 4. 상속관계 매핑 (0) | 2023.08.23 |
---|---|
@MappedSuperclass (0) | 2023.08.23 |
실습 3 - 다양한 연관관계 매핑 (1) | 2023.08.22 |
다대다 [N : N] (0) | 2023.08.21 |
일대일 [1 : 1] (0) | 2023.08.21 |