일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- Json 객체
- 저장소 이전
- MySQL
- 넘파이
- MVC
- 스프링 이메일 전송
- 자바
- 비밀번호 재설정 API
- Git
- jar빌드
- 값 타입
- 저장소 복제
- 우분투
- 스프링부트 OpenAI API
- HttpServletResponse
- JDBC
- api 개발
- 페이징 정렬
- JPA
- 프로그래머스
- springboot
- Chat GPT
- swap 메모리
- JPQL
- git 충돌 해결
- github 복제
- 파이썬
- 두수의 합 자바
- 서버 배포
- Servlet
- Today
- Total
현의 개발 블로그
[고급 매핑] 상속 관계 매핑 본문
객체에는 상속 관계가 존재하지만, 관계형 DB는 상속 관계가 존재하지 않는다.
슈퍼 타입-서브타입 관계라는 모델링 기법이 객체 상속과 유사하다.
상속 관계 매핑은 객체의 상속 구조를 DB의 슈퍼 타입-서브 타입 관계와 매핑하는 것이다.
상속 관계 매핑에는 3가지 방법이 있다.
1. 조인 전략: 각각의 테이블로 변환한다.
2. 단일 테이블 전략: 통합 테이블로 변환한다.
3. 구현 클래스마다 테이블 전략: 서브 타입 테이블로 변환한다.
각 방법들을 차례대로 살펴보자
조인 전략
조인으로 데이터를 구성한다.
공통 속성인 name, price은 Item 테이블에 저장되고, 나머지 속성들은 각자의 테이블에 저장된다.
위 전략을 사용할 때는 @Inheritance(strategy = InheritanceType.JOINED)를 매핑해 준다.
코드
각 엔티티를 생성해 준다.
Item 엔티티는 상속해 주는 용도로만 쓰이므로 추상클래스로 정의해 주었다.
@DiscriminatorColumn을 매핑하여 구분자 DTYPE 컬럼을 추가했다.
조인 전략에서는 해당 어노테이션이 없으면 DTYPE 컬럼이 생성되지 않는다.
상속받는 객체에 @DiscrminatorValue를 지정해주지 않으면, 엔티티 이름이 DTYPE으로 저장된다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED) // 조인전략
@DiscriminatorColumn
public abrstract class Item{
@Id @GeneratedValue
private Long id;
private String name;
private int price;
}
@Entity
public class Album extends Item {
private String artist;
}
@Entity
public class Movie extends Item{
private String director
private String actor
}
@Entity
public class Book extends Item{
private String author
}
Movie 객체를 저장하면 Item, Movie에 각각 insert query가 나간다.
데이터를 조회할 때는 ITEM_ID로 조인을 하는데 DTYPE으로 하위 객체들을 구분한다.
단일 테이블 전략
단일 테이블 전략에서는 논리 모델을 한 테이블에 다 합치고, 하위 객체들을 DTYPE으로 구분한다.
서비스 규모가 크지 않을 때 쓰기 좋은 전략이다.
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
위 어노테이션만 변경하면 단일 테이블 전략이 된다.
한 테이블에 모든 컬럼을 저장하기 때문에 DTYPE 없이는 구별할 수 없다.
따라서 @DiscriminatorColumn을 작성하지 않아도 DTYPE이 자동으로 생성된다.
DDL을 확인해 보면, Item 테이블만 생성된다.
다른 두 전략과 비교했을 때 삽입 쿼리와 조회 쿼리가 단순하다.
조인할 필요가 없기 때문에 성능이 좋다.
Movie에 값을 넣어주면 아래와 같은 insert 쿼리가 실행된다.
@DiscriminatorValue("M")을 매핑해 주었기에 Movie DTYPE이 M으로 들어간다.
구현 클래스마다 테이블 생성 전략
아래 어노테이션을 매핑하면 구현 클래스마다 테이블 생성 전략을 쓸 수 있다.
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
슈퍼 타입의 컬럼들을 서브 타입으로 내린다.
공통 속성인 name, price 컬럼들이 중복되도록 허용하는 전략이다.
구분자가 필요 없으므로 @DiscriminatorColumn이 사용되지 않는다.
DDL을 확인해 보면, 조인 전략 때와 달리 name, price는 Item이 아닌 Album 에 들어있다.
이 전략은 성능이 느리고 하위 클래스가 추가되면 변경하기 어렵기 때문에 사용하지 말자.
주요 어노테이션
상속 관계 매핑 3가지 방법 때 사용한 어노테이션을 정리해 보자.
- @Inheritance(strategy = InheritanceType.XXX)
- JOINED: 조인 전략
- SINGLE_TALBE: 단일 테이블 전략
- TABLE_PER_CLASS: 구현 클래스마다 테이블 전략
- @DiscriminatorColumn(name = “DTYPE”)
- @DiscriminatorValue(”XXX”)
상속관계 매핑 정리
조인전략
장점
- 테이블이 정규화되어 있다.
- 외래 키 참조 무결성 제약조건을 활용할 수 있다.
- 다른 엔티티에서 아이템을 참조할 때 서브 타입까지 갈 필요 없이, 슈퍼 타입의 아이디만 확인하면 된다.
- 저장 공간을 효율적으로 사용한다.
단점
- 조회 시 조인을 많이 사용해 성능이 저하된다.
- 조회 쿼리가 복잡하다.
- 데이터 저장 시 슈퍼 타입과 서브 타입 총 2번의 insert sql이 호출된다.
단일 테이블 전략
장점
- 조인이 필요 없으므로 일반적으로 조회 성능이 빠르다.
- 조회 쿼리가 단순하다.
단점
- 자식 엔티티가 매핑한 컬럼은 모두 null을 허용한다.
- 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다.
- 상황에 따라 조회 성능이 오히려 느려질 수 있다.
구현 클래스마다 테이블 생성 전략
장점
- 서브 타입을 명확히 구분하여 처리할 수 있다.
- NOT NULL 제약 조건을 사용할 수 있다.
단점
- 여러 자식 테이블을 함께 조회할 때 성능이 느리다.
- 자식 테이블을 통합해서 쿼리하기 어렵다.
결론
조인 전략과 단일 테이블 전략의 trade off를 고민해봐야 한다.
프로젝트가 단순하고 확장 가능성이 적으면 단일 테이블 전략을 사용하자.
비즈니스적으로 중요하고, 복잡하며, 확장될 가능성이 높으면 조인 전략을 사용자.
Reference
자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의
초급자를 위해 준비한 [웹 개발, 백엔드] 강의입니다. JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자
www.inflearn.com
[JPA] 상속관계 매핑 전략(@Inheritance, @DiscriminatorColumn)
상속관계 매핑객체는 상속관계가 존재하지만, 관계형 데이터베이스는 상속 관계가 없다.(대부분)그나마 슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사하다.상속관계 매핑이라는
ict-nroo.tistory.com
'스프링부트 이론 > JPA' 카테고리의 다른 글
[프록시와 연관관계 관리] 프록시 (0) | 2023.05.28 |
---|---|
[고급 매핑] @MappedSuperclass (0) | 2023.05.27 |
[다양한 연관관계 매핑] 실전 예제 (0) | 2023.05.23 |
[다양한 연관관계 매핑] 다대다 (0) | 2023.05.23 |
[다양한 연관관계 매핑] 일대일 (0) | 2023.05.23 |