객체 지향 언어에서는 '상속' 관계가 존재합니다.
그러나 관계형 데이터베이스에는 상속이라는 개념이 없는데요,
그래도 가장 유사한 관계가 '슈퍼타입 서브타입 관계'라는 모델링 기법입니다.
그리고 이 '슈퍼타입 서브 타입 관계'라는 논리적 모델을 실제 물리 모델(테이블)로 구현할 때는 3가지 방법이 있습니다.
1. 각각의 테이블로 변환시키고 조인하는 방법
JPA에서는 '조인 전략' (Joined)이라고 부릅니다.
구체적으로 엔티티 각각을 테이블로 모두 만들고 부모 테이블의 기본키를 받아서 이를 기본키이자 외래키로 사용합니다.
그래서 조회할 때 조인을 자주 사용합니다.
주의할 점은 객체는 타입으로 하위 객체들을 구분할 수 있지만
테이블은 타입의 개념이 없으므로 따로 구분하는 컬럼을 부모 테이블에 추가해야합니다.
이 구분 칼럼에 입력할 값으로는, 각 하위 엔티티들이 지정된 값으로 들어갑니다.
그 값은 애너테이션으로 아래와 같이 지정해준다. (구분 칼럼의 이름도 애너테이션으로 지어줄 수 있다.)
아래에서 구분 칼럼은 DTYPE입니다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name= "DTYPE") // 구분 칼럼의 이름도 애너테이션으로 지어줄 수 있다.
public abstract class Item {
//.. 생략
}
@DiscriminatorValue("A")
public class Album extends Item {
//.. 생략
}
@DiscriminatorValue("M")
public class Movie extends Item {
//.. 생략
}
@DiscriminatorValue("B")
public class Book extends Item {
//.. 생략
}
장점
- 테이블이 정규화됩니다.
- 외래 키 참조 무결성 제약조건을 활용할 수 있습니다.
- 저장공간을 효율적으로 사용합니다.
단점
- 조회할 때 JOIN이 많이 사용되서 성능 저하 우려
- 조회 쿼리가 복잡합니다.
- 데이터를 등록할 INSERT SQL을 2번 실행합니다. (슈퍼 테이블과 서브 테이블)
2. 통합된 하나의 테이블로 변환하는 방법
JPA에서는 '단일 테이블 전략'(Single Table)이라 합니다. 이름 그대로 테이블 하나에 모든 하위 테이블의 컬럼들을 넣고, 구분 칼럼(필수!)으로 어떤 하위 객체가 저장되었는지 구분합니다.
이로인해 JOIN을 사용하지 않으므로 일반적으로 가장 빠릅니다.
주의할 점은 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다는 점입니다.
각 데이터마다 사용되지 않는 칼럼에는 null을 입력할 수 있어야하기 때문입니다.
장점
- JOIN이 필요없어 일반적으로 조회 성능이 빠릅니다.
- 조회 쿼리가 단순합니다.
단점
- 자식 엔티티가 매핑한 칼럼들은 모두 null을 허용해야합니다.
- 단일 테이블에 모든 하위 테이블들의 데이터를 저장하므로 테이블이 더욱 커져 상황에 따라 조회성능이 오히려 느려질 수 있습니다.
1번에서 보여준 구분 칼럼의 값으로 넣을 값을 @DiscriminatorVlaue로 지정하지 않으면 기본으로 엔티티 이름으로 사용됩니다. ex) Movie, Book, Album
3. 서브 타입마다 각각의 테이블로 변환시키는 방법
JPA에서는 'Table-per-Concrete-Class' 전략이라 부릅니다.
자식 엔티티마다 테이블을 만들고, 자식 테이블이 필요한 칼럼이 모두 각자 테이블에 존재하는 것입니다.
(1번과 비슷해보이지만, 1번은 매 조회마다 부모 테이블과 조인해서 조회해야하는 방법인 반면
3번은 한 서브 타입의 테이블에 필요한 필드가 모두 들어있어 조인할 필요없이 조회할 수 있다는 차이가 있습니다.)
그리고, 1,2번과 다르게 구분 칼럼이 필요 없습니다.
장점
- 서브 타입을 구분해서 처리할 때는 효과적입니다.
- not null 제약 조건을 사용할 수 있습니다. (<--> 2번 방법과 차이)
단점
- 여러 자식 테이블을 함께 조회할 때 성능이 느립니다. (SQL UNION을 사용해야한다고 합니다)
- 자식 테이블을 통합해서 쿼리하기 어렵습니다.
'백엔드 개발하며 작성한 > 데이터베이스' 카테고리의 다른 글
[ORM] 연관관계의 주인을 정해야하는 이유 (0) | 2022.05.20 |
---|---|
[ORM > JPA] 영속성 컨텍스트 (0) | 2022.04.14 |
[MySQL]날짜/시간 타입과 TIMESTAMP 칼럼 생성 (0) | 2021.10.08 |
[MySQL Workbench] ERD를 SQL 코드로 변환하기 (0) | 2021.09.02 |
cmd로 MongoDB에 데이터 저장하기 (0) | 2021.05.20 |