본문 바로가기
  • 개발공부 및 일상적인 내용을 작성하는 블로그 입니다.
JPA

상속관계 매핑 - 2

by 방구석 대학생 2020. 10. 10.

"인프런 - 자바 ORM 표준 JPA 프로그래밍 강의를 듣고 작성한 글 입니다."

www.inflearn.com/course/ORM-JPA-Basic#

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다. 초급 웹 개발 프로그

www.inflearn.com

 

이번엔 삽입된 데이터들이 각각 어떤 도메인의 entity 인지 구별하기 위한 DTYPE 필드를 구현해보자.

 

- @DiscriminatorColumn 어노테이션

Item 클래스에 @DiscriminatorColumn 어노테이션을 선언해준 후 실행해보면 아래와 같은 hibernate SQL 을 출력하는 것을 볼 수 있다.

- Item.java

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public abstract class Item {

	@Id @GeneratedValue
	private Long id;

	private String name;
	private int price;
    
	// Getter, Setter
}

- hibernate SQL

Hibernate: 
    
    create table Item (
       DTYPE varchar(31) not null, // DTYPE 필드 생성
        id bigint not null,
        name varchar(255),
        price integer not null,
        primary key (id)
    )

 

위와 같이 @DiscriminatorColumn 어노테이션을 선언해준 후 데이터를 삽입한 다음 h2 콘솔을 통해 Item 테이블의 상태를 확인해보면 새로 생성된 DTYPE 컬럼에 삽입한 데이터의 도메인 이름이 들어가 있는 것을 확인할 수 있다.

- DTYPE 의 기본 값으로 데이터가 삽입된 도메인의 이름이 지정된다.

- @DiscriminatorColumn 어노테이션 에서 name 속성을 통해 변수명을 DTYPE 이 아닌 다른 이름으로 바꿔줄 수도 있다.

 

- h2 console 에서 데이터 select 결과

데이터 DTYPE 명시

되도록이면 위의 어노테이션을 사용하는게 좋은 이유?

데이터를 삽입하는 사람의 경우 데이터를 삽입할 때 어떤 테이블과 조인을 해야하는지 알고 있으나, DB 테이블 자체는 그것을 모르는 상태이다.

운영상에서나 DB에서 필요한 작업들(구체적으로 어떤 건지는 아직 잘 모르겠지만...) 을 생각해보면 되도록이면 DTYPE 필드를 통해 삽입된 데이터들이 각각 어떤 도메인 테이블의 데이터인지 구별해 주는 것이 좋다. 

 

그런데 여기서 만약 각 도메인 테이블의 분류명 까지 바꿔주어야 할 경우 @DiscriminatorValue(" ") 어노테이션을 사용해 줄 수 있다.

- 해당 어노테이션에서 큰 따옴표 안에 도메인 데이터의 분류명을 도메인 자체의 이름이 아닌 다른 이름으로 지정해 줄 수 있다.

- 위의 어노테이션을 통해 Movie 도메인 클래스의 DTYPE 명을 "M" 으로 바꿔주었을 경우 h2 콘솔에서 삽입된 데이터에 대해 다음과 같은 테이블이 나타나게 된다.

 

- Movie.java

@Entity
@DiscriminatorValue("M") // DTYPE 분류명 변경
public class Movie extends Item{

	private String director;
	private String actor;

	// Getter, Setter
}

 

- h2 console 에서 데이터 select 결과

데이터 DTYPE 값 변경

 

그런데 사실 테이블 조인 전략에서는 @DiscriminatorColumn 어노테이션이 없어도 된다.

- 테이블 조인 전략의 경우 어차피 도메인 별로 테이블이 분리되어 있기 때문에 name, price 와 같은 공통 속성의 데이터를 삽입해도 DTYPE 분류 없이도 구분할 수 있다.

- 하지만 단일 테이블 전략의 경우 테이블 별로 구분되어 있지 않기 때문에 name, price 와 같이 공통 속성 데이터를 삽입해야 할 경우 반드시 DTYPE 컬럼을 통해 도메인 을 분류해 주어야 한다.

- 위의 설명과 같이 단일 테이블 전략의 경우 반드시 DTYPE 컬럼과 같이 각 도메인 데이터를 분류하는 필드가 필요하기 때문에 @DiscriminatorColumn 어노테이션을 선언해 주었든, 그렇지 않든 간에 자동적으로 테아블에 DTYPE 필드가 생성된다.

 

- 단일 테이블 전략 논리 모델과 테이블

- Item.java

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
// @DiscriminatorColumn 어노테이션 생략
public abstract class Item {

	@Id @GeneratedValue
	private Long id;

	private String name;
	private int price;
    
	// Getter, Setter
}

 

- hibernate SQL

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)
    ) // 한 테이블에 슈퍼 타입과 서브 타입 테이블의 필드들이 모두 생성되었다.
Hibernate: 
    /* insert hellojpa.Movie
        */ insert 
        into
            Item
            (name, price, actor, director, DTYPE, id) 
        values
            (?, ?, ?, ?, 'M', ?) // insert 문이 딱 한번만 들어가는 것을 확인 할 수 있다.
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' // select 또한 테이블 조인을 할 필요가 없다.

 

- h2 console

 

* 단일 테이블 전략의 장점은 데이터의 삽입이 단 한번으로 끝나기 때문에 테이블 조인 전략보다 성능면에서 이점이 있다.

 

여기서 재밌는 점?

실습을 진행하다 보면 객체의 상속 관계 매핑 전략을 테이블 조인 전략에서 단일 테이블 전략으로 바꿨음에도 불구하고 코드에서는 거의 달라진 것이 없다.(어노테이션에서 전략만 바꿨을 뿐이다.)

-> 이것이 바로 JPA 의 큰 장점 중 하나이다.

 

애플리케이션을 조인 전략으로 설계하다 성능이 너무 안 나와서 단일 테이블 전략으로 바꿔야 할 경우, JPA 를 쓰지 않고 개발한다고 가정하면 소스 코드를 정말 많이 바꿔주어야 한다.(SQL 쿼리도 마찬가지로 많이 바꿔야 한다.)

 

하지만 JPA 를 활용하면 전략을 바꾸더라도 많은걸 바꿀 필요 없이 @Inheritance 어노테이션에서 전략만 새로 바꿔주고 매핑하면 그만이다.

그만큼 코딩하는 시간이 확 줄어들게 되는 것이다.

 

 

다음글에선 구현 클래스마다 테이블을 생성하는 전략에 대해 알아보자.

'JPA' 카테고리의 다른 글

@MappedSuperclass 어노테이션  (0) 2020.10.10
상속관계 매핑 - 3  (0) 2020.10.10
상속관계 매핑 - 1  (0) 2020.10.10
실전 예제 3 - 다양한 연관관계 매핑  (0) 2020.10.06
실전 예제 2 - 연관관계 매핑 기초  (0) 2020.10.06