본 글은 인프런의 김영한님 강의 자바 ORM 표준 JPA 프로그래밍 - 기본편 을 수강하며 기록한 필기 내용을 정리한 글입니다.
-> 인프런
-> 자바 ORM 표준 JPA 프로그래밍 - 기본편 강의

슈퍼타입 - 서브타입슈퍼타입 - 서브타입은 논리적으로 설계되는 모델이며, 이를 실제 DB 상에서 물리적으로 구현되는 방법에는 3가지가 있다.
-> 노란색 열쇠모양 : PK
-> 파란색 열쇠모양 : PK, FK
- 저장해야 하는 음악 정보 데이터 : 이름, 매체, 연주자, 작곡가
- 데이터 저장
- 연주자와 작곡가 데이터는 음악 테이블에, 이름과 매체 데이터는 문화 테이블에 저장하고 FK로 연결한다.
- 문화 테이블의 DTYPE 컬럼에 본 데이터가 음악 정보임을 저장한다.
(ex. "MUSIC")- 데이터 조회
- 음악 테이블의 FK 값을 통해 문화 테이블과 join하여 조회한다.


슈퍼타입에 해당하는 컬럼들이 서브타입 테이블에서 모두 중복되더라도 그냥 각자가 갖고 있는 방식이다.2. DB 상속관계 구현 전략 에서 다루었던 3가지 전략 모두 JPA 상에서 매핑할 수 있다.@Inheritance : 상속관계 매핑@DiscriminatorColumn : DTYPE 컬럼 관리@DiscriminatorValue : DTYPE에 저장되는 데이터 관리< Culture >
@Entity
public class Culture {
@Id @GeneratedValue
@Column(name = "CULTURE_ID")
private Long id;
@Column(name = "NAME")
private String name;
@Column(name = "MEDIA")
private String media;
}
< Music >
@Entity
public class Music extends Culture {
@Column(name = "MUSICIAN")
private String musician;
@Column(name = "COMPOSER")
private String composer;
}
< Movie >
@Entity
public class Movie extends Culture {
@Column(name = "ACTOR")
private String actor;
@Column(name = "DIRECTOR")
private String director;
}
< Drawing >
@Entity
public class Drawing extends Culture {
@Column(name = "ARTIST")
private String artist;
}
@Inheritance(strategy = InheritanceType.JOINED)@DiscriminatorColumn@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public class Culture {
@Id @GeneratedValue
@Column(name = "CULTURE_ID")
private Long id;
@Column(name = "NAME")
private String name;
@Column(name = "MEDIA")
private String media;
}

Music music = new Music();
music.setName("music1");
music.setMedia("Television");
music.setMusician("10cm");
music.setComposer("10cm");
entityManager.persist(music);
entityTransaction.commit();


Music music = new Music();
music.setName("music1");
music.setMedia("Television");
music.setMusician("10cm");
music.setComposer("10cm");
entityManager.persist(music);
entityManager.flush();
entityManager.clear();
Music findMusic = entityManager.find(Music.class, music.getId());

3-1. 공통 필드 묶은 후 join 방식 매핑 에서 부모 클래스의 어노테이션 내용만 바꿔주면 된다.@Inheritance(strategy = InheritanceType.SINGLE_TABLE)@DiscriminatorColumn@DiscriminatorColumn 어노테이션은 생략해도 된다.@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
public class Culture {
...
3-1. 공통 필드 묶은 후 join 방식 매핑 에서 활용했던 main 코드를 그대로 돌려보면, 다음과 같이 CULTURE 테이블로만 동작하는 것을 확인할 수 있다.

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)@DiscriminatorColumn 제거@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Culture {
...


@DiscriminatorColumn 어노테이션에 name 속성을 추가해 주면 된다.@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "CATEGORY")
public class Culture {
...
@DiscriminatorValue 어노테이션을 자식 클래스에 적용하면 된다.@Entity
@DiscriminatorValue("MUSIC_CATEGORY")
public class Music extends Culture {
...
3-3. 묶지 않고 각자 갖도록 구현 방식 매핑 방식은 최대한 쓰지 않도록 한다.< 3-3 방법의 문제점 >
- 만약 음악, 영화, 그림 중 어느 데이터인지 모르는 상황에서 id값만 알고 있다고 가정해 보자
- 그렇다면 다음과 같이 코드를 짤 수 있다.
Culture findCulture = entityManager.find(Culture.class, id);- 그럼 여기에 다 못담을 만큼 무시무시한 쿼리가 나간다.
- MUSIC, MOVIE, DRAWING 싹다 UNION으로 묶어서 조회한다.
- id값만으로 찾아야 하기 때문에 음악, 영화, 그림 모든 테이블을 다 뒤져봐야 하기 때문이다.
- 즉, 부모 클래스가 갖는 필드의 정보만으로 찾으려 할 경우, 음악, 영화, 그림으로 특정되지 않아 결국 싹다 뒤지는 것이다.
3-1. 공통 필드 묶은 후 join 방식 매핑, 3-2. 하나의 테이블로 구현 방식 매핑 둘 중 하나를 활용하게 될 텐데, 각각의 장단점은 다음과 같다.
3-1. 공통 필드 묶은 후 join 방식 매핑장단점
- 장점
- 일단 본 방식이 가장 정석이라고 볼 수 있다.
- 테이블이 정규화 되어 있다.
- FK 참조 무결성 제약조건을 활용할 수 있다.
- CULTURE 테이블의 CULTURE_ID와 MUSIC 테이블의 CULTURE_ID가 동일한 값을 갖는다.
- 따라서 만약 MUSIC 데이터 중 CULTURE 테이블에 있는 데이터만 조회해야 할 경우, 다른 테이블들 볼 필요 없이 CULTURE 테이블에서 CULTURE_ID 값만으로 조회가 가능하다.
- 저장 공간의 효율화가 가능하다.
- 테이블이 정규화 되어 있으므로 저장 공간 활용 자체가 효율적이다.
- 단점
- 조회 과정에서 join이 많이 사용된다. 성능이 저하될 수 있다.
- 하지만 join도 잘 맞추면 성능이 저하되지 않고, 일단 저장공간에서 효율성을 가져가기 때문에 프로젝트 구조에 따라 성능이 더 좋아질 수도 있다. (큰 그림을 보자)
- 조회 쿼리가 복잡하다.
- 데이터 저장 과정에서 INSERT 쿼리가 2번 나간다.
- 슈퍼타입과 서브타입 테이블에 나눠서 저장해야 하므로
- 사실 하나의 테이블로 구현하는 방식에 비해 많이 복잡하다는 것 자체가 하나의 단점이 된다.
3-2. 하나의 테이블로 구현 방식 매핑장단점
- 장점
- join이 필요 없으므로, 일반적으로 조회 성능이 빠르다.
- 조회 쿼리가 단순하다.
- 단점
- 자식 엔티티가 매핑할 컬럼들은 모두 null이 허용되어야 한다.
- 만약 MUSIC 데이터가 저장되면, 나머지 MOVIE, DRAWING에 해당하는 컬럼들은 모두 null이 되어야 하므로.
- 이는 치명적인 단점이다.
- 하나의 테이블에 모든 데이터를 저장하기 때문에 테이블이 매우 커질 수 있고, 상황에 따라 조회 성능이 오히려 느려질 수 있다.
- 하지만 일반적으로는 성능이 빠르다.