테이블 구조를 설계하다보면 중복항목, 혹은 분리된 테이블을 하나의 PK로 관리하고 싶은 충동을 느낄때가 있습니다. 이것은 특히 JPA를 사용하면서 이런경우 더 큰 충동을 일으켰습니다.
그러다가 JPA @Inheritance기능을 찾게되어 기록합니다.
먼저 @Inheritance는 3가지 전략을 지원합니다.
전략 | 상세 |
SINGLE_TABLE | 한개의 테이블로 관리합니다. |
TABLE_PER_CLASS | 부모테이블의 컬럼들을 자식테이블에 전부 추가한다 |
JOINED | 부모테이블의 pk값을 자식테이블에 넣어주고 join전략을 통해 데이터의 연관관계를 유지한다. |
공식 문서나 블로그의 글을 보면서 생각한 DB의 구조는 SINGLE_TABLE는 클래스 하나 TABLE_PER_CLASS 와 JOINED는 각 클래스마다 테이블이 생성될 것으로 예상한다.
아래 몇가지 예시를 만들어 보며 이해한 내용을 추가한다.
아래 사진처럼 테이블 구조를 짜서 크게 SINGLE_TABLE과 JOINED의 차이를 테스트 해보았다.
extends 받는 클래스에 @DiscriminatorValue안에 있는 value 값이 테이블 이름이 되며 상속 받는 테이블에는 최상위 부모 Root 부모에 있는 PK값이 자동으로 추가된다.
root클래스만 자세하게 작성한 내용입니다. @Inheritance를 선언한 테이블이 상위 테이블이 되며 상속받을 테이블이 각각 extends받는 형태로 진행됩니다.
package com.example.demo;
import javax.persistence.*;
@Entity
@Inheritance
@DiscriminatorColumn
public class RooootClassesses {
@Id@GeneratedValue
private Long id;
private String name2;
}
실제로 실행시켜보면 테이블하나에 모든 컬럼이 추가된 것을 볼 수 있습니다.
반대로 전략에 @Inheritance(strategy = InheritanceType.JOINED)를 주어 join 전략을 사용하게 하면 아래 사진처럼 테이블이 각각 클래스마다 생성되며 상위 클래스를 상속받은 하위 클래스는 pk값으로 상위 클래스의 값을 가지게 된다.
ex) 최 하위 테이블인 sub_suba 테이블에 데이터를 넣으면 자동으로 suba와 roooot_classesses에 데이터가 들어가며 pk값은 roooot_classesses에 pk값으로 저장됩니다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "types")
public class RooootClassesses {
@Id@GeneratedValue
private Long id;
private String name2;
}
단점
하지만 @Inheritance를 실제 업무환경, 서비스에 사용하는 곳을 찾아보기 힘들었습니다.
실제로는 @manytoone과 같은 형태로 설계되어있고 아예 분리되어있는 곳도 많았습니다.
이유를 찾아보니 @Inheritance는 싱글 테이블의 경우 필요 없는 null 공간이 많이 생겨 데이터 축적 효율이 좋지않을 수 있고 Join과 같은 여러 테이블을 구축하는 경우에는 join을 활용한 쿼리가 많이 필요해서 보통의 경우보다 쿼리효율이 좋지 못한 이유가 실 환경에서 사용하지 않는 대부분의 이유였습니다.
서비스 속도의 대부분을 차지하는게 DB관련 로직이다 보니 쿼리에서 효율이 좋지 못한 시스템은 살아남지 못하는 것 같습니다.
Reference
@Inheritance 값을 지정하지 않으면 기본값으로 single_table이 선언되어 한개의 테이블이 생성됩니다.
'IT 이야기 > Spring' 카테고리의 다른 글
[MSA] MSA 스터디 1장 Eureka (0) | 2022.11.18 |
---|---|
[Spring] AWS S3를 연동하기 (0) | 2022.01.03 |
댓글