본 글은 인프런의 김영한님 강의 자바 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이 되어야 하므로.
- 이는 치명적인 단점이다.
- 하나의 테이블에 모든 데이터를 저장하기 때문에 테이블이 매우 커질 수 있고, 상황에 따라 조회 성능이 오히려 느려질 수 있다.
- 하지만 일반적으로는 성능이 빠르다.