일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- embededtype
- httppie
- Git
- 자바제너릭
- dockercmd
- sql
- 에이치투데이터베이스
- JPAproxy
- 스프링부트
- JDBC connection pool
- springbootH2
- spring
- OSIV
- JPAmapping
- javageneric
- jpa
- 임베디드타입
- springbootproxy
- gitinitial
- 스프링부트기본설정
- 데이터베이트h2
- springboot기본설정
- jpqlquery
- JPA값타입
- JPA Hint & Lock
- 제이피큐엘쿼리
- Open EntityManager
- 이해와 원리
- MySqlType
- JPA프록시
Archives
- Today
- Total
빡코
[JPA][개념] 상속관계 본문
상속관계매핑
•관계형 데이터베이스는 상속관계X
•슈퍼타입 서브타입 관계라는 모델링기법 이객체 상속과 유사
•상속 관계 매핑: 객체의 상속과 구조와 DB의 슈퍼타입 서브타입 관계를 매핑
슈퍼타입 서브타입 논리모델을 실제 물리 모델로 구현하는 방법
•각각 테이블로 변환 -> 조인전략
•통합 테이블로 변환 -> 단일테이블전략
•서브타입 테이블로 변환 -> 구현 클래스마다 테이블 전략
•각각 테이블로 변환 -> 조인전략
•통합 테이블로 변환 -> 단일테이블전략
•서브타입 테이블로 변환 -> 구현 클래스마다 테이블 전략
주요 어노테이션
•@Inheritance(strategy=InheritanceType.XXX)
•JOINED: 조인전략
•SINGLE_TABLE: 단일 테이블 전략
•TABLE_PER_CLASS: 구현 클래스 마다 테이블 전략
•@DiscriminatorColumn(name=“DTYPE”)
•@DiscriminatorValue(“XXX”)
조인 전략
조인 전략
•장점
•테이블 정규화
•외래키 참조 무결성 제약조건 활용가능
•저장 공간 효율화
•단점
•조회시 조인을 많이 사용, 성능저하
•조회 쿼리가 복잡함
•데이터 저장시 INSERT SQL 2번호출
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn //엔티티명이 들어가게 된다.
public class Item {
@Id @GeneratedValue
private Long id ;
private String name;
private int price;
}
package hellojpa;
import javax.persistence.Entity;
@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;
}
}
Movie movie = new Movie();
movie.setDirector("aaa");
movie.setActor("bbb");
movie.setName("바람과 함께 사라지다");
movie.setPrice(1000);
em.persist(movie);
em.flush();//db저장
em.clear();//1차캐시 날리기
Movie findMovie = em.find(Movie.class, movie.getId());
System.out.println("findMovie = " + findMovie);
//로그
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@3a8d467e
(?, ?, ?)
findMovie = hellojpa.Movie@3a8d467e
*Item 의 Id와 Movie의 Id는 동일하다. 부모 Item의 Id는 PK, 자식 테이블 Movie의 Id는 PK이면서 동시에 FK이다.
@DiscriminatorColumn: 부모 테이블에서 적용
@DiscriminatorValue : 자식테이블 명
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn //엔티티명이 들어가게 된다.
public class Item {
}
@Entity
@DiscriminatorValue("M")
public class Movie extends Item {
}
create table Item (
DTYPE varchar(31) not null,
id bigint not null,
name varchar(255),
price integer not null,
primary key (id)
)
단일 테이블 전략
단일 테이블 전략
•장점
•조인이 필요 없으므로 일반적으로 조회성능이 빠름
•조회쿼리가 단순함
•단점
•자식엔티티가 매핑한 칼럼은 모두 null 허용
•단일테이블에 모든 것을 저장하므로 테이블이 커질 수 있다.
상황에 따라서 조회성능이 오히려 느려질 수 있다
*한 테이블에 다 올리고 DTYPE 컬럼으로 구분한다.
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)
)
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@63d5874f
* insert 와 select 쿼리가 심플하게 나간다.
구현클래스마다테이블전략
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@DiscriminatorColumn
public abstract class Item {
}
구현 클래스마다테이블전략
•이 전략은 데이터베이스설계자와 ORM 전문가 둘 다 추천 X
•장점
•서브타입을 명확하게 구분해서 처리할 때효과적
•not null 제약조건사용가능
•단점
•여러 자식테이블을 함께 조회할 때성능이 느림(UNION SQL 필요)
•자식테이블을 통합해서 쿼리 하기 어려움
부모 클래스로 조회시 전체 테이브을 조회한다. 비추천
Movie movie = new Movie();
movie.setDirector("aaa");
movie.setActor("bbb");
movie.setName("바람과 함께 사라지다");
movie.setPrice(1000);
em.persist(movie);
em.flush();
em.clear();
Item findItem = em.find(Item.class, movie.getId());
System.out.println("findMovie = " + findItem);
//실행 로그
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_6_0_,
item0_.director as director2_6_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=?
findMovie = hellojpa.Movie@141d3d43
@ MappedSuperClass
공통 매핑 정보가 필요할 때 사용 (id, name)
ex) Team 과 Member 클래스에 공통으로 들어가는 속성들을 BaseEntity 클래스로 별도 생성하여 각 클래스에서 상속하여 사용한다.
@MappedSuperclass
public class BaseEntity {
private String createBy;
private LocalDateTime createDate;
private String lastModifiedBy;
private LocalDateTime lastModifiedDate;
public String getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public LocalDateTime getCreateDate() {
return createDate;
}
public void setCreateDate(LocalDateTime createDate) {
this.createDate = createDate;
}
public String getLastModifiedBy() {
return lastModifiedBy;
}
public void setLastModifiedBy(String lastModifiedBy) {
this.lastModifiedBy = lastModifiedBy;
}
public LocalDateTime getLastModifiedDate() {
return lastModifiedDate;
}
public void setLastModifiedDate(LocalDateTime lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
}
//실행로그
//각 테이블에 해당 필드가 생성된 것을 확인할 수 있다.
create table Member (
MEMBER_ID bigint not null,
createBy varchar(255),
createDate timestamp,
lastModifiedBy varchar(255),
lastModifiedDate timestamp,
USERNAME varchar(255),
LOCKER_ID bigint,
TEAM_ID bigint,
primary key (MEMBER_ID)
)
create table Team (
TEAM_ID bigint not null,
createBy varchar(255),
createDate timestamp,
lastModifiedBy varchar(255),
lastModifiedDate timestamp,
name varchar(255),
primary key (TEAM_ID)
)
•상속관계매핑X
•엔티티X, 테이블과매핑X
•부모 클래스를 상속받는 자식 클래스에 매핑 정보만 제공
•조회, 검색불가(em.find(BaseEntity) 불가)
•직접 생성해서 사용할 일이 없으므로 추상 클래스 권장
•테이블과 관계없고, 단순히 엔티티가 공통으로 사용하는 매핑정보를 모으는 역할
•주로 등록일, 수정일, 등록자, 수정자 같은 전체엔티티에서 공통으로 적용하는 정보를 모을 때사용
•참고: @Entity 클래스는 엔티티나 @MappedSuperclass로지 정한 클래스만상 속가능
•주로 등록일, 수정일, 등록자, 수정자 같은 전체엔티티에서 공통으로 적용하는 정보를 모을 때사용
•참고: @Entity 클래스는 엔티티나 @MappedSuperclass로지 정한 클래스만상 속가능
예제
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
public abstract class Item extends BaseEntity{
@Id
@GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
private String name;
private int price;
private int stockQuantity;
@ManyToMany(mappedBy = "items")
private List<Category> categories = new ArrayList<>();
}
@MappedSuperclass
public abstract class BaseEntity {
private String createBy;
private LocalDateTime createDate;
private String lastModifiedBy;
private LocalDateTime lastModifiedDate;
}
book, Movie, Album은 Item 클래스를 상속한다.
'Java > JPA' 카테고리의 다른 글
[JPA][개념] 값 타입 (0) | 2023.03.23 |
---|---|
[JPA][개념] 프록시와 연관관계 정리 (0) | 2023.03.23 |
[JPA][개념]다양한 연관관계 매핑 (0) | 2023.02.17 |
[JPA][개념] 엔티티 매핑 (0) | 2023.02.14 |
[JPA][개념] 영속성 관리 (0) | 2023.02.10 |