728x90
반응형
상속 관계 매핑
- 객체의 상속 구조와 DB의 슈퍼타입 서브타입 관계를 매핑하는 것
- 객체는 상속관계가 있지만 관계형 데이터베이스는 상속 관계가 없다.
- 슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사하다.
- 슈퍼타입 서브타입 논리 모델을 실제 물리 모델로 구현하는 방법
(1) 각각 테이블로 변환 -> 조인 전략
(2) 통합 테이블로 변환 -> 단일 테이블 전략
(3) 서브타입 테이블로 변환 -> 구현 클래스마다 테이블 전략
주요 어노테이션
@Inheritance(strategy = InheritanceType.XXX)
JOINED
: 조인 전략SINGLE_TABLE
: 단일 테이블 전략TABLE_PER_CLASS
: 구현 클래스마다 테이블 전략@DiscriminatorColumn(name = "DTYPE")
구분자 컬럼 설정 (기본값 : DTYPE)@DiscriminatorValue("XXX")
구분자 컬럼값 설정 (기본값 : 엔티티명)
조인 전략
- 엔티티를 각각의 테이블로 변환하여 조인 관계를 맺는 전략
- 장점
- 테이블 정규화가 되어있어 설계가 깔끔하여 정석으로 많이 사용된다.
- 외래키 참조 무결성 제약조건을 활용할 수 있다.
- 저장공간을 효율적으로 사용할 수 있다. - 단점
- 조회할 때 조인을 많이 사용하여 성능이 저하될 수 있다.
- 조회 쿼리가 복잡하다.
- 데이터 저장 시 insert SQL이 2번 호출된다.
구조
예제
Entity
- Item.java
@Entity
@Inheritance(strategy = InheritanceType.JOINED) // 기본 전략은 SINGLE_TABLE
public abstract class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
// getter, setter
}
- Album.java
@Entity
public class Album extends Item { // 상속 관계
private String artist;
// getter, setter
}
- Movie.java
@Entity
public class Movie extends Item { // 상속 관계
private String director;
private String actor;
// getter, setter
}
- Book.java
@Entity
public class Book extends Item { // 상속 관계
private String author;
private String isbn;
// getter, setter
}
Main
- JpaMain.java
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("AAA");
movie.setActor("BBB");
movie.setName("킹콩");
movie.setPrice(8000);
em.persist(movie);
// 1차캐시 비우기
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();
}
}
동작 결과
(1) Table DDL
(2) Insert SQL 및 결과
(3) Select SQL 및 결과
단일 테이블 전략
- 각각의 엔티티를 하나의 통합 테이블로 변환하여 사용하는 전략
- 장점
- 조인이 필요 없으므로 일반적으로 조회 성능이 빠르다.
- 조회 쿼리가 단순하다. - 단점
- 자식 엔티티가 매핑한 컬럼은 모두 NULL이 허용되어야 한다. (데이터 무결성 입장에서 애매한 부분이 있다.)
- 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다. 상황에 따라서 조회 성능이 오히려 느려질 수 있다.
구조
예제
Entity
- Item.java
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) // 기본 전략은 SINGLE_TABLE
public abstract class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
// getter, setter
}
- Album.java
, Movie.java
, Book.java
는 이전 예제와 동일
Main
- JpaMain.java
는 이전 예제와 동일
동작 결과
(1) Table DDL
(2) Insert SQL 및 결과
(3) Select SQL 및 결과
구현 클래스마다 테이블 전략
- 각각의 자식 엔티티에 부모 엔티티의 정보가 포함되어 서브타입 테이블로 변환하여 사용하는 전략
- 데이터베이스 설계자와 ORM 전문가 둘 다 추천하지 않는다.
- 장점
- 서브 타입을 명확하게 구분해서 처리할 때 효과적이다.
- NOT NULL 제약조건 사용 가능 - 단점
- 여러 자식 테이블을 함께 조회할 때 성능이 느리다. (union SQL 필요)
- 자식 테이블을 통합해서 쿼리하기 어렵다.
구조
예제
Entity
- Item.java
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) // 기본 전략은 SINGLE_TABLE
public abstract class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
// getter, setter
}
- Album.java
, Movie.java
, Book.java
는 이전 예제와 동일
Main
- JpaMain.java
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("AAA");
movie.setActor("BBB");
movie.setName("킹콩");
movie.setPrice(8000);
em.persist(movie);
// 1차캐시 비우기
em.flush();
em.clear();
// 조회(하위 클래스)
Movie findMovie = em.find(Movie.class, movie.getId());
System.out.println("findMovie = " + findMovie);
// 개별테이블 전략 상위 클래스 조회 (각각의 하위 테이블 조회하여 union)
Item item = em.find(Item.class, movie.getId());
System.out.println("Item = " + item);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
동작 결과
(1) Table SQL
(2) Insert SQL 및 결과
(3) Select SQL 및 결과 (하위 클래스 조회)
(4) Select SQL 및 결과 (상위 클래스 조회)
@DiscriminatorColumn(name = "DTYPE")
- 구분자 컬럼을 설정하는 어노테이션으로 부모 클래스에서 사용한다. 기본값은 DTYPE
- 단일 테이블 전략은 해당 어노테이션 없이도 테이블 내에서 데이터를 구분할 수 없기 때문에 구분자 컬럼이 필수로 생성된다.
예제
- Item.java
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) // 기본 전략은 SINGLE_TABLE
@DiscriminatorColumn // 구분자 컬럼 지정
public abstract class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
// getter, setter
}
동작 결과
@DiscriminatorValue("XXX")
- 부모 클래스에서 생성한 구분자 컬럼에 들어갈 값을 설정하는 어노테이션. 기본값은 엔티티명
예제
- Movie.java
@Entity
@DiscriminatorValue("M") // 구분자 컬럼 내 값 지정(기본값: 엔티티명)
public class Movie extends Item {
private String director;
private String actor;
// getter, setter
}
동작 결과
매핑 정보 상속 (@MappedSuperclass)
- 객체 입장에서 공통 매핑정보를 상속 받아서 사용하기 위함
- 상속관계 매핑이 아니다.
- 엔티티가 아니고 테이블과 매핑되는 것도 아니다.
테이블과 관계 없고, 단순히 엔티티가 공통으로 사용하는 매핑 정보를 모으는 역할 - 부모 클래스를 상속 받는 자식 클래스에 매핑 정보만 제공
- 조회, 검색(
EntityManager.find(BaseEntity)
) 불가 - 직접 생성해서 사용할 일이 없으므로 추상 클래스로 구현하는 것을 권장
- 주로 등록일, 등록자, 수정일, 수정자 같은 전체 엔티티에서 공통으로 적용하는 정보를 모을때 사용
@Entity
클래스는 엔티티(@Entity
로 지정한 클래스) 나@MappedSuperclass
로 지정한 클래스만 상속 가능하다.
구조
예제
공통 클래스 (@MappedSuperclass)
- BaseEntity.java
@MappedSuperclass
public abstract class BaseEntity {
@Column(name = "INSERT_MEMBER") // 매핑 컬럼 지정 가능
private String createdBy;
private LocalDateTime createdDate;
@Column(name = "UPDATE_MEMBER")
private String lastModifiedBy;
private LocalDateTime lastModifiedDate;
// getter, setter
}
Entity
- Item.java
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) // 기본 전략은 SINGLE_TABLE
@DiscriminatorColumn
public abstract class Item extends BaseEntity { // 매핑 정보 상속(BaseEntity)
@Id @GeneratedValue
private Long id;
private String name;
private int price;
// getter, setter
}
- Movie.java
@Entity
@DiscriminatorValue("M")
public class Movie extends Item { // 매핑 정보를 상속받은 부모 클래스를 상속 받는다.
private String director;
private String actor;
// getter, setter
}
동작 결과
728x90
반응형
'Dev > JPA' 카테고리의 다른 글
[JPA] 프록시와 연관관계 관리 (0) | 2021.08.27 |
---|---|
[JPA] 실습 - 상속관계 매핑 (0) | 2021.08.25 |
[JPA] 실습 - 다양한 연관관계 매핑 (0) | 2021.08.23 |
[JPA] 다양한 연관관계 매핑 (0) | 2021.08.23 |
[JPA] 실습 - 연관관계 매핑 시작 (0) | 2021.08.18 |
댓글