Be ready to study forever - 개발자 꿈나무

[JPA] 고급 매핑 - 3 본문

Programming/JPA

[JPA] 고급 매핑 - 3

루눌룹 2021. 1. 23. 20:31

객체지향의 상속을 관계형 DB에서는 어떻게 표현할 수 있을까?

관계형 DB에서는 그나마 상속과 비슷하게 구현하는 방법은 슈퍼타입과 서브타입 모델링을 사용하여 구현할 수 있다.

그림과 같이 서브타입 테이블에 기본키에 외래키를 걸어버리면 1:1관계가 성립하면서 조인을 해서 두 테이블을 상속관계처럼 사용할 수 있다. 그렇지만, 다른 전략으로도 객체의 상속관계를 관계형DB에 표현할 수 있는데, 3가지 전략이 있다

-      조인전략(JOINED)

-      단일 테이블 전략(SIGNLE_TABLE)

-      구현 클래스마다 테이블 생성 전략(TABLE_PER_CLASS)

 

상속 매핑하는 방법)

이것 역시 어노테이션을 활용한다. 3가지 어노테이션이 있는데:

@Inheritance(strategy=InheritanceType.XXX) stategy를 설정해주면 된다. 부모 클래스에 선언한다. default 전략은 SINGLE_TABLE(단일 테이블 전략)이다.

-      InheritanceType 종류

JOINED - @Inheritance(strategy=InheritanceType. JOINED)

SINGLE_TABLE - @Inheritance(strategy=InheritanceType. SINGLE_TABLE)

TABLE_PER_CLASS - @Inheritance(strategy=InheritanceType. TABLE_PER_CLASS)

 

 

@DiscriminatorColumn(name="DTYPE")

부모 클래스에 선언한다. 하위 클래스를 구분하는 용도의 컬럼이다. 관례는 default = DTYPE 그리고 자식 클래스의 @DiscriminatorValue("XXX")어노테이션에 xxx가 정의되어 있지 않다면 테이블 이름이 값으로 들어오게 된다.

 

@DiscriminatorValue("XXX")

하위 클래스에 선언한다. 엔티티를 저장할 때 슈퍼타입의 구분 컬럼에 저장할 값을 지정한다.

어노테이션을 선언하지 않을 경우 기본값으로 클래스 이름이 들어간다.

 

코드를 보면서 이해해보자면

ITEM(부모클래스)

@Entity
@Inheritance(strategy = InheritanceType.XXX) // 상속 구현 전략 선택

@DiscriminatorColumn(name="DTYPE") //자식클래스를 구별할 칼럼이름
public class Item {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    private int price;
}

 

ALBUM(자식클래스)

@Entity
@DiscriminatorValue("XXX") //부모 클래스의 DTYPE에 들어갈 이름 적지 않을 경우 자식테이블의 이름이 들어감
public class Album extends Item {

    private String artist;
}

 

MOVIE(자식클래스)

@Entity
@DiscriminatorValue("XXX") //부모 클래스의 DTYPE에 들어갈 이름 적지 않을 경우 자식테이블의 이름이 들어감
public class Movie extends Item {

    private String director;
    private String actor;
}

 

BOOK(자식클래스)

@Entity
@DiscriminatorValue("XXX") //부모 클래스의 DTYPE에 들어갈 이름 적지 않을 경우 자식테이블의 이름이 들어감
public class Book extends Item {

    private String author;
    private String isbn;
}

 

상속 매핑 전략)

조인전략(JOINED)

그림과 같이 슈퍼타입과 서브타입의 테이블을 생성하는데

장점:

-      테이블의 정규화가 가능하다

-      외래 키 참조의 무결성을 지킬 수 있다

-      정규화 되어 중복되지 않음으로 저장공간의 효율화가 가능하다

단점:

-      조회시 조인을 사용해야 한다

-      데이터 저장시 INSERT쿼리가 두번 발생된다

단일 테이블 전략(SIGNLE_TABLE)

그림과 같이 상속을 그냥 한 테이블에 때려 박아서 구현하는 방법으로 간단하다.

장점:

-      조인이 필요 없으므로 조회가 빠르다

-      쿼리가 단순하다

단점:

-      자식 엔티티의 값에 NULL을 허용해야 한다. (치명적일 수도…)

-      테이블이 너무 커지게 될 경우 상황에 따라서 성능이 안 좋을 수가 있다.

구현 클래스마다 테이블 생성 전략(TABLE_PER_CLASS)

장점:

-      서브타입을 명확하게 구분할 때 효과적이다

-      NULL값을 허용하지 않아도 된다.

단점:

-      여러 자식을 함께 조회할 때 성능이 매우 느리다.

-      자식테이블을 통합해서 쿼리하기가 힘들다

**김영한님의 말에 따르면, 구현 클래스마다 테이블 전략은 사용하지 않는 것이 좋다고 한다. 이유는, 자식테이블을 통합해서 무언가를 결과를 내야 할 경우 JOINUNION이 필요함으로 성능이 매우 구려진다고그리고 간단한 테이블의 경우에는 단일테이블 전략을, 일반적인 경우라면 조인전략을 사용하는 것이 좋다고 하셨다

 

상속관계가 아닌 단순히 반복되는 값을 재활용 하고 싶다면? - @MappedSuperclass

때로는 createdAt, updatedAt, updatedBy같이 거의 모든 테이블에 들어가는 칼럼인 반복되는 필드를 적는건 매우 고통스럽다. 그럴경우엔 @MappedSuperclass를 사용해보자!

 

@MappedSuperClass?

테이블과 관계가 없고 단지 엔티티에서 공통으로 사용하는 정보를 모아 중복되는 코드를 제거하고 싶은때 사용한다. 주로 등록일, 수정일 과 같이 엔티티에서 공통으로 사용하는 필드를 모아서 적용하면 중복도 제거되고 생산성도 높아진다!

**@Entity클래스는 같은@Entity클래스(DB에서 상속으로 처리)@MappedSuperclass(DB에서 칼럼으로만 처리)만 상속받을 수 있다.

그림에서 보듯이 중복되는 코드를 한 클래스에 모아서 @MappedSuperclass로 묶어주면 손쉽게 중복되는 코드 제거 완료! 하지만 DB에서는 상속으로 적용되지 않는다.

'Programming > JPA' 카테고리의 다른 글

[JPA] 값 타입  (0) 2021.01.24
[JPA] 엔티티매핑  (0) 2021.01.24
[JPA] 다양한 연관관계 매핑-2  (0) 2021.01.23
[JPA] 연관관계 매핑 기초 - 1  (0) 2021.01.23
[JPA] 영속성 컨텍스트란?  (0) 2021.01.23
Comments