상속관계 매핑

최주영·6일 전
0

JPA

목록 보기
4/5

✅ 상속관계 매핑

  • DB 즉 관계형 데이터베이스는 상속 관계라는 것이 없음
  • 슈퍼타입 서브타입의 관계 가 자바의 객체 상속이라 비슷함


왼쪽 그림은 자바의 상속 상태를 나타내며
오른쪽 그림에서 Item은 슈퍼타입 Album, Movie, Book 은 서브타입을 의미한다


✅ 상속관계 매핑 방법 3가지

슈퍼타입 서브타입 논리 모델을 실제 물리모델로 구현하는 방법 3가지

  • 조인 전략 : 각각 테이블로 변환하는 방법으로 기본적으로 많이 사용함
  • 단일 테이블 전략 : 통합 테이블로 변환
  • 구현 클래스마다 테이블 전략 : 서브타입 테이블로 변환

위 3가지의 전략을 사용하기 위해서는 다음과 같은 어노테이션 필요하다
@Inheritance(strategy=InheritanceType.XXX
어노테이션을 사용하지 않으면 기본적으로 JPA는 단일 테이블 전략 이 적용됨

XXX 에는 각 전략에 따라 명칭이 달라진다

JOINED : 조인 전략
SINGLE_TABLE : 단일 테이블 전략
TABLE_PER_CLASS : 구현 클래스마다 테이블 전략

@DiscriminatorColumn : 자식 테이블들을 구별할 수 있는 DTYPE 이라는 컬럼이 생김
기본 값은 DTYPE으로 명칭을 바꾸고 싶으면 -> @DiscriminatorColumn(name = "") -> name 안에 명칭
조인 전략에서는 이 어노테이션을 사용하는 것이 편하다
하지만 단일 테이블 전략에서는 이 어노테이션이 필수 -> 없으면 구별할 수 없음

@DiscriminatorValue(“XXX”)
자식클래스에서 사용하는 것으로 @DiscriminatorColumn 컬럼 안에 구분되는 값이 들어갈 때 사용
어노테이션을 사용하지 않으면 기본값으로 해당 자식 객체의 Entity 값이 들어감
어노테이션을 사용하면 XXX 값에 원하는 명칭으로 변경 가능


✅ 조인 전략

장점

  • 테이블 정규화
  • 외래 키 참조 무결성 제약조건 활용이 가능함
  • 저장공간 효율화

단점

  • 조회시 조인을 많이 사용해서 성능이 저하 = 조회 쿼리가 복잡
  • 데이터 저장시 INSERT SQL이 2번호출됨 = 분할되어있기 때문에

@Entity
@Inheritance(strategy = InheritanceType.JOINED) // 조인 전략
public class Item{
	@Id @GeneratedValue
    private Long id;
    
    private String name;
    private int price;
}
@Entity
public class Album extends Item {
	private String artist
}
@Entity
public class Movie extends Item {
	private String director;
    private String actor;
}
@Entity
public class Book extends Item {
	private String author;
    private String isbn;
}
// main함수
Movie movie = new Movie();
movie.setDirector("최최최");
movie.setActor("김김김");
movie.setName("박박박"); // 부모 컬럼을 사용
movie.setPrice("5000"); // 부모 컬럼을 사용

em.persist(movie) // persist() 호출하면 조인 할 수 있는 상태로 값이 추가됨 

em.flush(); // 영속성 컨텍스트에 있는 것들을 DB안에 다 넣기
em.clear(); // 영속성 컨텍스트 초기화 = 1차 캐시 비워짐

Movie findMovie = em.find(Movie.class, movie.getId()); // Movie와 Item이 조인된 상태로 조회됨

✅ 단일 테이블 전략

장점

  • 조인이 필요 없어서 일반적으로 조회 성능이 빠름
    = 조회 쿼리가 단순함
  • INSERT 문도 한번에 처리 가능 (자식 테이블 INSERT 할 필요 X)

단점

  • 하나의 테이블에 모든 테이블의 컬럼들을 다 넣은 방식이라
    자식 엔티티가 매핑한 컬럼은 모두 NULL을 허용함 = 데이터 무결성 입장에선 애매함
  • 단일 테이블에 모든 것을 저장하는 방식이라 테이블이 커짐에 따라서 조회서능이 느려질 수 있음

코드는 위 조인전략 코드에서 한부분만 변경하면 된다

@Inheritance(strategy = InheritanceType.SINGLE_TABLE) // 단일 테이블 전략


✅ 구현 클래스마다 테이블 전략

결론적으로 이 전략은 사용하지 않는 것이 좋다

장점

  • 서브타입을 명확하게 구분할 때 유용
  • not null 제약조건 사용 가능

단점

  • 조회 할 때, UNION ALL 로 모든 테이블을 조회하기 때문에 비효율적임
  • 자식 테이블을 통합해서 쿼리하기 어려움

✅ 매핑 정보 상속

  • 공통 매핑 정보가 필요할 때 사용함
  • @MappedSuperClass
  • 상속관계 매핑이 아님
  • 직접 생성하는 것이 아니라서 추상클래스 로 생성 권장
  • 테이블과 관계 없고, 단순히 엔티티가 공통으로 사용하는 매핑 정보를 모으는 역할
  • 엔티티가 아니며, 테이블과 매핑하는 것이 아님
    즉 밑에 예시에서 BaseEntity 테이블을 생성하는 것이 아님
    = 조회 검색 불가 em.find(BaseEntity) 불가
    가정 : 모든 테이블에 생성날짜, 생성한사람, 마지막수정날짜, 마지막수정한사람을 추가해야 할 때
@MappedSuperClass 
public class BaseEntity { // 요구 조건들만 따로 클래스를 만들어서 넣음
	private String createdBy;
    private LocalDateTime createdDate;
    private String lastModifiedBy;
    private LocalDateTime lastModifiedDate;
    
    // getter + setter 생략
}
@Entity
public class Member extends BaseEntity { // 위 클래스를 상속받으면 사용 가능Member 코드와 동일
}

@Entity @MappedSuperclass 차이

위 예시에서 BaseEntity에 @Entity 를 적용시 상속관계로 사용하겠다는 의미 (부모 테이블 조회 수정 가능)
하지만 @MappedSuperclass 를 적용하면 속성 만 상속 받을 때 사용 (부모 테이블 조회 수정 불가능)


profile
우측 상단 햇님모양 클릭하셔서 무조건 야간모드로 봐주세요!!

0개의 댓글