1. 상속 관계 매핑이란?
슈퍼타입 테이블, 서브타입 테이블을 자바에서 상속관계인 것 처럼 사용하는 방법입니다.
2. 상속 관계 매핑 전략의 종류
1) JOINED (조인전략)
슈퍼타입과 서브타입을 식별관계로 사용하는 방법입니다.
2) SINGLE_TABLE (단일 테이블 전략)
슈퍼타입과 서브타입을 하나의 테이블로 생성하는 전략입니다.
3) TABLE_PER_CLASS (타입 별 테이블 생성 전략) (비추천)
파일 타입 별로 테이블을 생성하는 전략입니다.
3. 상속 관계 매핑 적용
1) FileInfo.java
import javax.persistence.*;
@Entity
@Table(name = "file_info")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "data_type")
public abstract class FileInfo {
@Id
@GeneratedValue
private Long id;
private String url;
@Column(name = "org_name")
private String orgName;
private String length;
/*
setter, getter 생략
*/
}
슈퍼 타입 클래스입니다. JOINED 전략을 사용할 경우 슈퍼 타입과 서브 타입은 식별관계가 되므로 서브 타입은 슈퍼타입 기본키를 외래키로 가짐과 동시에 기본키로 선언합니다.
@Inheritance 어노테이션을 이용해 JOINED, SINGLE_TABLE, TABLE_PER_CLASS 전략을 선택할 수 있으며, JOINED 전략을 보통 사용합니다. 하지만 검색속도 최적화를 위해 SINGLE_TABLE 전략을 사용하기도 합니다.
(TABLE_PER_CLASS 전략은 웬만하면 사용하지 않는 것을 추천합니다.)
@DiscriminatorColumn 어노테이션은 JOINED, SINGLE_TABLE 전략일 경우 사용하며, 서브타입의 구분값을 저장하는 컬럼입니다. name 속성을 이용해 구분 컬럼의 이름을 지정할 수 있습니다.
2) Image.java, Sound.java, Video.java
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue(value = "IMAGE")
public class Image extends FileInfo {
private String type;
private int width;
private int height;
/*
setter,getter 생략
*/
}
@Entity
public class Sound extends FileInfo {
private Long runtime;
private String type;
/*
setter,getter 생략
*/
}
@Entity
public class Video extends FileInfo {
private Long runtime;
private String type;
/*
setter,getter 생략
*/
}
서브 타입 클래스입니다. @DiscriminatorColumn 어노테이션을 사용했을 경우 서브타입 구분 값에 클래스 명이 저장됩니다.
@DiscriminatorValue 어노테이션을 사용했을 경우 서브타입 구분 값을 지정할 수 있습니다.
4. 테스트
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-persistence");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Image image = new Image();
image.setOrgName("google_icons.png");
image.setUrl("https://ssl.gstatic.com/gb/images/p1_c9bc74a1.png");
image.setType("png");
//image 영속화
em.persist(image);
// 쓰기 지연에 쌓아둔 SQL을 DB에 전송한다.
em.flush();
// 영속성 캐시를 제거한다.
em.clear();
//image 조회
Image findImage = em.find(Image.class, image.getId());
System.out.println(findImage.getUrl());
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
@Inheritance(strategy = InheritanceType.JOINED) 전략으로 테스트했으며, Image를 저장하면 file_info와 image 테이블에 각각 저장됩니다.
그리고 image를 조회할 경우 file_info와 image 테이블을 조인해서 select 합니다.
# commit 시 작동되는 쿼리
# Image 저장 시, file_info와 image 테이블에 각각 저장한다.
insert
into
file_info
(length, org_name, url, data_type, id)
values
(?, ?, ?, 'IMAGE', ?)
insert
into
Image
(height, type, width, id)
values
(?, ?, ?, ?)
# image 조회 시, image 테이블과 file_info 테이블을 조인해서 select한다
select
image0_.id as id2_0_0_,
image0_1_.length as length3_0_0_,
image0_1_.org_name as org_name4_0_0_,
image0_1_.url as url5_0_0_,
image0_.height as height1_1_0_,
image0_.type as type2_1_0_,
image0_.width as width3_1_0_
from
Image image0_
inner join
file_info image0_1_
on image0_.id=image0_1_.id
where
image0_.id=?
도움이 되셨다면 공감 버튼 한번씩 눌러주세요!
'IT > JPA & Hibernate' 카테고리의 다른 글
[JPA] 엔티티 매핑 어노테이션 정리 (0) | 2021.05.10 |
---|---|
[JPA] 기본키 자동 생성 전략(Primary Key) (0) | 2021.05.10 |
[JPA] @MappedSuperclass 사용법 (0) | 2021.05.08 |
[JPA] Hibernate 연동 방법 (0) | 2021.05.05 |
[JPA] 영속성 컨텍스트 (0) | 2020.02.03 |