JPA - 상속매핑
JPA 상속매핑
관계형 데이터베이스는 상속 관계가 없다.
하지만객체는 상속관계의 개념을 가지고 있다.
JPA에서는 이러한 상속관계를 지원한다.
- 슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사
- 상속관계 매핑 : 객체의 상속과 구조와 DB의 슈퍼타입 서브타입 관계를 매핑
상속관계 매핑
JPA에서 지원하는 데이터베이스 상속 전략은 3가지가 있다.
데이터베이스의 상속 전략 3가지
-
조인 전략 / 부모의 PK를 FK받아 조인을 통한 데이터 조회 (타입으로 구분)
-
단일 테이블 전략 / 하나의 테이블에 데이터를 다 넣는다. (타입으로 구분)
-
구현 클래스마다 테이블 전략 / 공통 테이블이 아닌 각각 테이블 구현
@Inheritance(strategy=InheritanceType.XXX)
기본 extends를 이용하면 JPA는 기본 전략으로 단일 테이블 전략을 사용한다.
부모가 되는 Entity에 @Inheritance(strategy=InheritanceType.XXX)
어노테이션만 작성하면 쉽게 상속 매핑을 구현 할 수 있다.
-
JOINED(조인)
-
SINGLE_TABLE(단일 테이블) / 기본 전략 (default)
-
TABLE_PER_CLASS(구현 클래스 테이블)
조인 전략
조인전략
-
@Inheritance(strategy = InheritanceType.JOINED)
-
자식 Entity에서 부모를 상속 받는다.
-
자식 테이블에 부모 PK가 FK면서 PK로 설정된다
-
find() 조회시 부모와 자식을 조인해서 값을 가져온다
Parent
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
}
@Entity
public class Book extends Item{
private String author;
private String isbn;
}
@Entity
public class Movie extends Item {
private String director;
private String actor;
}
@Entity
public class Album extends Item{
private String artist;
}
Table 생성

장점
- 테이블의 정규화 (정석)
- 외래키 참조 무결성 제약조건 활용가능
- 저장공간 효율화
단점
- 조회시 조인을 많이 사용, 성능 저하
- 조회 쿼리가 복잡함
- 데이터 저장시 INSERT 2번 호출
싱글전략
싱글전략
-
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
-
자식Entity를 부모 Entity에 통합하여 하나의 테이블 생성
-
성능적으로 제일 좋음 (조회 , 등록 쿼리 1번 실행)
-
default로 DTYPE이 생성된다.
Parent
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorValue
public class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
}
Table 생성

싱글전략은 자식들의 데이터가 하나의 테이블에 들어가기 떄문에 구분지을수 있는 컬럼이 필요하다.
JPA에서는 @DiscriminatorColumn을 지원한다.
@DiscriminatorColumn
-
부모 Entity에 작성한다.
-
부모 테이블에 DTYPE 컬럼이 추가되고 구분 하는 데이터가 들어간다.
-
객체지향적으로는 문제는 없지만 DB접근시 구분을 위해 넣는게 좋다.
-
조인전략은 굳이 각각 부모와 1:1 매핑이 되기에 굳이 필요 없지만 단일 테이블 전략은 꼭 필요하다.
@DiscriminatorValue
-
자식 테이블에 추가하여 DTYPE에 들어가는 데이터값 설정가능
-
default name Entity
장점
- 테이블 조인이 필요가 없으므로 조회 성능이 빠르다
- 조회 쿼리가 단순하다
단점
- 자식 엔티티가 매핑한 컬럼은 모두 null 허용해야한다
- 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있으므로 상황에 따라 조회 성능이 오히려 느려질 수 있다.
구현 클래스 전략
구현 클래스 전략
-
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
-
DTYPE이 필요없다
-
조인전략과 비슷하지만 부모테이블이 존제하지 않는다.
-
조회시 문제가 생길 수 있다. (부모엔티티로 조회시)
Parent
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Item {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
}
이 전략은 데이터베이스 설계자와 ORM 전문가 둘다 추천하지 않는다
장점
- 서브 타입을 명확하게 구분해서 처리할 떄 효과적이다
- not null 제약조건 사용 가능하다
단점
- 여러 자식 테이블을 함꼐 조회할 때 성능이 느리다 (UNION SQL)
- 자식 테이블을 통합해서 쿼리하기 어렵다 (통계 및 정산)
매핑 정보 상속
테이블을 만들다 보면 생성일 , 수정일과 같이 테이블에 중복해서 들어가고 꼭 필요한 컬럼들이 존제한다.
이러한 중복 문제를 @MappedSuperclass를 사용하면 쉽게 해결이 가능하다.
@MappedSuperclass
공통으로 Entity가 속성값을 사용할때 사용한다
ex) 생성일 , 수정일 등…
-
상속관계 매핑 X
-
엔티티 X , 테이블과 매핑 X
-
부모 클래스를 상속 받는 자식 클래스에 속성 매핑 정보만 제공
-
조회 , 검색 불가 (Entity로서 사용이 불가능하다)
-
직접 생성해서 사용할 일이 없으므로 추상 클래스 권장
@MappedSuperclass Class
@MappedSuperclass
public abstract class BaseEntity {
private String createBy;
private LocalDateTime createdDate;
private String lastModifedBy;
private LocalDateTime lastModifedDate;
}
@Entity
public class Member extends BaseEntity {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "name")
private String username;
}
@Entity
public class Team extends BaseEntity {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
}
Member와 Team에는 생성일과 생성자, 수정일, 수정자의 데이터가 필요하여 BaseEntity를 만들어 중복 코드를 제거했다.
테이블 생성시 Member와 Team이 생성이 되며 각각 생성일 , 생성자 , 수정일 , 수정가 컬럼이 추가될 것이다.
-
테이블과 관계 없고 , 단순히 엔티티가 공통으로 사용하는 매핑 정보를 모으는 역할
-
주로 등록일, 수정일 , 등록자 수정자 같은 전체 엔티티에서 공통으로 적용하는 정보를 모을 때 사용
-
참고 : @Entity 클래스는 엔티티나 @MappedSuperclass로 지정한 클래스만 상속 가능
Leave a comment