객체는 상속관계가 있습니다.
그런데 관계형 데이터베이스에는 상속관계와 비슷하게 지원하는 기능이 있긴 하지만 객체의 상속관계랑은 조금 다르다.
관계형 데이터베이스에는 객체지향 언어에서의 상속 개념이 없다.
대신 관계형 데이터베이스에서는 슈퍼타입 서브타입 관계라는 모델링 기법이 상속과 유사하다.
상속관계 매핑
객체의 상속구조와 DB의 슈퍼타입, 서브타입 관계를 맵핑하는 것
위의 사진처럼 물리 모델로 구현을 할 수가 있는데 첫번째가 조인 전략이라는 방식이다.
엔티티마다 모두 테이블로 만들어주고 부모의 기본키를 기본키 + 외래키로 사용한다. 때문에 조회할 때 조인을 사용한다.
다만 객체는 타입이 있는데 테이블은 타입에 개념이 없으니 따로 DTYPE 등의 컬럼을 추가해야한다.
// Item 엔티티
@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;
...
}
// Album 엔티티
@Entity
@DiscriminatorValue("A")
public class Album extends Item{
private String artist;
...
}
// Movie 엔티티
@Entity
@DiscriminatorValue("M")
public class Movie extends Item{
private String director;
private String actor;
...
}
장점
단점
특징
단일 테이블 전략은 논리 모델을 한 테이블로 다 합쳐버리는 것이다.
앨범, 영화, 책의 컬럼 들을 모두 ITEM 테이블에 넣어버리는 것이다. 이때 구분 컬럼(DTYPE)을 추가해 어떤 자식 데이터가 저장되어 있는지 구분 가능하다.
EX) DTYPE로 컬럼명을 놓고 테이블의 데이터가 앨범, 영화, 책 중 어디에 해당하는 데이터인지 나타내준다.
// Item 엔티티
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DisciminatorColumn(name = "DTYPE")
...
// 자식 엔티티
@Entity
@DiscriminatorValue("A")
...
@Entity
@DiscriminatorValue("M")
...
조인전략과 형식은 비슷한데 Inheritance.SINGLE_TABLE을 사용한다. 또한 모든 테이블이 하나로 통합되어있기 때문에 구분 컬럼은 필수다.
장점
단점
구현 클래스마다 테이블 전략은 자식 테이블이 부모 테이블의 모든 것을 다 가지고 있는 형태다. 그래서 자식 엔티티마다 테이블을 다 만들어 준다.
구현 클래스마다 테이블 전략은 조인 전략과 비슷해보이지만 다르다.
앨범, 무비, 북 테이블이 Name, Price 정보를 각각 다 들고 있는 것이다.
데이터가 중복되긴 하지만 이런 방법도 존재한다. DB 입장에서는 어떤 방법으로 구현하더라도 JPA에서는 다 맵핑이 가능하다.
// Item 엔티티
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
...
// 자식 엔티티
@Entity
@DiscriminatorValue("A")
...
@Entity
@DiscriminatorValue("M")
...
InheritanceType.TABLE_PER_CLASS 속성을 지정해주면 된다.
그러면 구현 클래스마다 테이블 전략을 사용한다. 일반적으로 사용하지 않는다.
이 전략은 데이터베이스 설계자와 ORM 전문가 둘 다 추천X
장점
단점
특징
위 방법들은 모두 부모 자식 클래스 모두 데이터베이스 테이블과 매핑했는데,
부모 클래스는 테이블과 매핑하지 않고 자식 클래스에게 매핑 정보만 제공하고 싶을때 @MappedSuperclass를 사용한다.
@MappedSuperclass는 추상 클래스와 비슷한데 @Entity는 실제 테이블과 매핑되지만 이는 그렇지 않다. 단순히 매핑 정보를 상속할 목적으로만 사용된다.
Member 테이블과 Seller 테이블에 공통 속성을 부모 클래스로 모으고 객체 상속 관계로 나타낼수 있다.
// BaseEntity
@MappedSuperclass
public abstract class BaseEntity{
@Id @GeneratedValue
private Long id;
private String name;
...
}
// Member 엔티티
@Entity
public class Member exteds BaseEntity{
// ID, NAME 상속
private String email;
...
}
// Seller 엔티티
@Entity
public class Seller exteds BaseEntity{
// ID, NAME 상속
private String shopName;
...
}
BaseEntity에서 객체들의 공통 매핑 정보를 정의하였고 자식 엔티티들이 이를 상속해 매핑 정보를 받았다. 여기서 BaseEntity는 테이블과 매핑할 필요가 없고 자식 엔티티에게 공통 매핑 정보만 제공한다.
@AttributeOverrides를 사용해 부모로부터 받은 매핑 정보를 재정의할 수 있고
@AssociationOverrides를 사용해 연관관계를 재정의 할수도 있다.
@MappedSupperclass 특징
출처
자바 ORM 표준 JPA 프로그래밍 강의
게시글 속 자료는 모두 위 강의 속 자료를 사용했습니다.