티스토리 뷰
객체의 상속관계를 테이블로 어떻게 표현할 수 있는 알아봅시다.
1. 슈퍼 타입, 서버 타입
관계형 데이터베이스에서는 객체지향 언어에서 다루는 상속이라는 개념이 없습니다.
대신 슈퍼 타입 서브 타입 관계라는 모델링 기법이 있는데, 이것이 객체의 상속과 유사한 방법입니다.
슈퍼 타입 서브 타입 관계를 실제 테이블로 구현하기 위해서 3가지 방법이 있습니다.
1. 조인 전략
2. 단일 테이블 전략
3. 구현 클래스마다 테이블 전략
각각의 전략에 대해서 자세하게 알아보도록 하겠습니다.
2. 조인 전략
조인 전략은 부모 클래스는 물론이고 부모 클래스를 상속받는 자식 클래스들까지 각각의 테이블로 변환하는 전략입니다.
예시를 통해 자세하게 설명드리도록 하겠습니다.
상품을 위한 Item 클래스가 있고 이를 상속 받는 Album, Movie, Book 클래스가 있다고 가정해 보겠습니다.
부모 클래스와 자식 클래스 각각을 테이블로 변환한 모습을 그림을 통해 확인할 수 있습니다.
실제로 코드로 구현해보도록 하겠습니다.
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="DTYPE")
public abstract class Item { // 부모 클래스
@Id @GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
private String name;
private int price
}
@Entity
@DiscriminatorValue("A")
public class Album extends Item { // 자식 클래스(Album)
private String artist;
...
}
1. @Inheritance(strategy=InheritanceType.JOINED)를 통해 조인 전략을 사용할 수 있습니다.
2. 부모 클래스에 @DiscriminatorColumn(name="DTYPE") 을 적어 "DTYPE"이라는 이름의 구분 컬럼을 생성합니다.
3. 자식 클래스에 @DiscriminatorValue("A")을 적어 Album 엔티티가 저장될 때 "DTYPE" 컬럼에 "A" 값을 저장합니다.
Album 엔티티를 저장할 때 DB 모습을 확인하면 Item 테이블의 "DTYPE" 컬럼에 "A" 값이 저장된 모습을 확인할 수 있습니다.
이러한 조인 전략의 장단점을 살펴보도록 하겠습니다.
우선, 장점부터 보도록 하겠습니다.
1. 테이블 정규화
각 클래스에 대해 별도의 테이블을 생성함으로써 테이블 구조가 정규화됩니다.
2. 외래 키 참조 무결성 제약 조건 활용 가능
부모 클래스와 자식 클래스 간의 관계를 외래 키로 명확히 정의함으로써 참조 무결성을 보장할 수 있습니다.
3. 저장공간 효율적 사용
중복 데이터를 피하고, 각 테이블에 필요한 속성만 저장하기 때문에 저장공간을 효율적으로 사용할 수 있습니다.
단점으로는
1. 조회 시 조인 많이 사용
데이터를 조회할 때 부모 테이블과 자식 테이블을 조인해야 하기 때문에 성능이 저하될 수 있습니다.
2. 조회 쿼리가 복잡
여러 테이블을 조인해야 하기 때문에 조회 쿼리가 복잡해질 수 있습니다.
3. 데이터 등록 시 INSERT SQL 2번 실행
데이터를 등록할 때 부모 테이블과 자식 테이블에 각각 INSERT 문을 실행해야 하기 때문에 데이터 등록 시에도 성능 저하가 발생할 수 있습니다.
3. 단일 테이블 전략
단일 테이블 전략은 상속 관계에 있는 모든 엔티티를 하나의 테이블에 저장하는 전략입니다.
조인 전략과 같은 예시를 통해서 살펴보도록 하겠습니다.
부모 클래스와 자식 클래스들은 ITEM 테이블 하나에 저장하는 모습을 그림을 통해 확인할 수 있습니다.
마찬가지로 실제로 코드로 구현해보도록 하겠습니다.
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="DTYPE")
public abstract class Item {
@Id @GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
private String name;
private int price
}
@Entity
@DiscriminatorValue("A")
public class Album extends Item {
private String artist;
...
}
1. @Inheritance(strategy=InheritanceType.SINGLE_TABLE)를 통해 단일 테이블 전략을 사용할 수 있습니다.
2. 다른 어노테이션들은 조인 전략에서 설명했으니 생략하도록 하겠습니다.
Album 엔티티와 Movie 엔티티가 저장되는 DB 모습을 확인해 보겠습니다.
🤔 조인 전략과 단일 테이블 전략 코드는 거의 달라지는게 없네요?
맞습니다. 코드상으로는 @Inheritance 어노테이션을 활용해 전략을 구분할 뿐 부모 클래스의 컬럼명, 자식 클래스의 컬럼값은 지정하는 방식은 동일합니다. 부모 클래스와 자식 클래스의 컬럼명, 컬럼값을 지정한 후 @Inheritance 어노테이션을 활용해 조인 전략, 단일 테이블 전략을 선택해 주시면 됩니다.
이젠 단일 테이블 전략의 장단점을 살펴보도록 하겠습니다.
우선 장점은
1. 조회 성능 빠름
모든 엔티티가 하나의 테이블에 저장되기 때문에 조인이 필요 없어서 조회 성능이 빠릅니다.
2. 조회 쿼리가 단수함
하나의 테이블에서 데이터를 조회하기 때문에 조회 쿼리가 단순합니다.
단점으로는
1. 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 함
하나의 테이블에 모든 엔티티를 저장하기 때문에, 각 엔티티가 사용하지 않은 컬럼에도 null 값을 허용해야 합니다.
2. 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있음
모든 엔티티를 하나의 테이블에 저장하기 때문에, 테이블이 커질 수 있습니다. 이로 인해 성능 저하나 메모리 부담이 발생할 수 있습 니다.
3. 상황에 따라 조회 성능이 오히려 느려질 수 있음
테이블에 많은 엔티티가 저장될 경우, 테이블의 크기가 커져서 성능이 저하될 수 있습니다 .
4. 구현 클래스마다 테이블 전략
구현 클래스마다 테이블 전략은 부모 클래스를 구현한 자식 클래스들만 테이블로 변환하는 전략입니다.
마찬가지로 같은 예시를 통해서 살펴보도록 하겠습니다.
자식 클래스들만 테이블로 변환된 모습을 그림을 통해 확인할 수 있습니다.
코드로 구현해 보도록 하겠습니다.
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
@DiscriminatorColumn(name="DTYPE")
public abstract class Item {
@Id @GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
private String name;
private int price
}
@Entity
@DiscriminatorValue("A")
public class Album extends Item {
private String artist;
...
}
1. @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)를 통해 구현 클래스마다 테이블 전략을 사용할 수 있습니다.
2. 다른 어노테이션들은 조인 전략에서 설명했으니 생략하도록 하겠습니다.
📌 이 전략은 데이터베이스 설계자와 ORM 전문가 둘 다 추천하지 않는 전략입니다.
따라서 조인이나 단일 테이블 전략을 고려하는 것이 좋습니다.
본 포스팅은 자바 ORM 표준 JPA 프로그래밍을 참고하여 작성했습니다.
'JPA' 카테고리의 다른 글
엔티티의 생명주기 (0) | 2024.06.07 |
---|---|
상속 관계 매핑 - @MappedSuperclass (0) | 2024.06.06 |
다양한 연관관계 매핑 (0) | 2024.05.01 |
연관관계의 주인 (0) | 2024.04.25 |
양방향 연관관계(@OneToMany, mappedBy) (0) | 2024.04.25 |
- @joincolumn
- Redis
- @Entity
- 비영속
- 단일 테이블 전략
- 즉시 로딩
- JPA
- @Table
- @GeneratedValue
- 조인 전략
- @ManyToOne
- 영속성 컨텍스트
- @OneToMany
- 연관관계
- 준영속
- 비동기
- @Cacheable
- 엔티티 매니저
- 변경감지
- @MappedSuperclass
- 메일
- 스키마 자동 생성
- mappedBy
- 1차 캐시
- 인메모리 db
- @Id
- onetoone
- @TransactionalEventListener
- N + 1
- 최적화