ORM 표준 JPA 프로그래밍 - 고급 매핑

링딩·2022년 9월 4일
0

ORM 표준 JPA

목록 보기
6/6

상속관계

상속관계 매핑

• 관계형 데이터베이스는 상속 관계가 X
슈퍼타입 ∘ 서브타입 관계라는 모델링 기법이 객체 상속과 유사

• 상속관계 매핑:
'객체의 상속과 구조'와 - 'DB의 슈퍼타입 서브타입 관계'를 매핑

전략들

슈퍼타입 서브타입 논리 모델을 -> '실제 물리 모델'로 구현하는 방법

• 각각 테이블로 변환 -> 조인 전략
• 통합 테이블로 변환 -> 단일 테이블 전략
• 서브타입 테이블로 변환 -> 구현 클래스마다 테이블 전략

주요 어노테이션

코드 (Item)

@Entity
@Inheritance(strategy = InheritanceType.JOINED) //전략 선택
@DiscriminatorColumn(name="DTYPE")
public class Item {

    @Id
    @GeneratedValue
    private Long id;

    private String name;
    private int price;

}

@Entity
@DiscriminatorValue("A")
public class Album extends Item{

    private String artist;
}
  • @Inheritance(strategy=InheritanceType.XXX)
    => 전략 선택을 해주면 된다.
    • JOINED: 조인 전략
    • SINGLE_TABLE: 단일 테이블 전략
    • TABLE_PER_CLASS: 구현 클래스마다 테이블 전략
  • @DiscriminatorColumn(name=“DTYPE”)
    : 이 '이름'으로 클래스를 구분 짓는다는 의미
  • @DiscriminatorValue(“XXX”)
    : 위에서 명시한 컬럼에서 각각의 클래스에 따른 값을 미리 지정해줌
    ex) "A","B", 이니셜로


1. 조인 전략

  • 장점
    • 테이블 정규화
    • 외래 키 참조 무결성 제약조건 활용가능
    • 저장공간 효율화
    • ITEM이 분리되어 있다보니 구현클래스마다 테이블 전략이랑 비슷하다. 바로 Order에서 Item을 찾아오려고 할 때 albumn이나 movie,book을 뒤질 필요없이 Item을 꺼내가면 됨
  • 단점
    • 조회시 조인을 많이 사용, 성능 저하
    • 조회 쿼리가 복잡함
    • 데이터 저장시 INSERT SQL 2번 호출

2.단일 테이블 전략


  • 장점
    • 조인이 필요 없으므로 일반적으로 조회 성능이 빠름
    • 조회 쿼리가 단순함
  • 단점
    • 자식 엔티티가 매핑한 컬럼은 모두 null 허용
    • 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다. 상황에 따라서 조회 성능이 오히려 느려질 수 있다.
    -> (보통 이런 경우는 임계점이 넘을 떄나 발생)
    -> 흔한 상황이 x

3. 구현 클래스마다 테이블 전략 [쓰지마라]

왜 쓰지말아야 할까?
묶어내야 시스템이 통합이 가능한데 각 클래스로 완전히 분리되어서 새로운 것이 추가될 때마다 일일히 가서 코드를 돌려야 한다.

  • 조인전략이랑 비슷함
  • Item 테이블을 없애버리고 그 속성을 다 하위 클래스로 넘겨버림
  • 장점
    • 서브 타입을 명확하게 구분해서 처리할 때 효과적
    • not null 제약조건 사용 가능
  • 단점
    • 여러 자식 테이블을 함께 조회할 때 성능이 느림(UNION SQL 필요)
    • 자식 테이블을 통합해서 쿼리하기 어려움

강사님은 단일 테이블 전략을 많이 쓴다. 복잡하고 비즈니스 적으로 중요하면 조인 전략을 쓰신다 하셨다.



@MappedSuperclass

주 목표: 공통 매핑 정보가 필요할 때 사용(id, name)

특징

• 상속관계 매핑X
• 엔티티X, 테이블과 매핑X
-> 쿼리에도 안 나옴
• 부모 클래스를 상속 받는 자식 클래스에 매핑 정보만 제공
조회, 검색 불가(em.find(BaseEntity) 불가)
• 직접 생성해서 사용할 일이 없으므로 추상 클래스 권장

• 테이블과 관계 없고, 단순히 엔티티가 공통으로 사용하는 매핑정보를 모으는 역할

사용하는 곳

: 주로 등록일, 수정일, 등록자, 수정자 같은 전체 엔티티에서 공통으로 적용하는 정보를 모을 때 사용

참고

extends는 보통 @Entity 클래스의 상속관계나, @MappedSuperclass로 지정한 클래스의 경우에만 쓰인다.

사용법

@MappedSuperclass
public abstract class BaseEntity {

    private String createBy;
    private LocalDateTime createDate;
    private String lastModifiedBy;
    private LocalDateTime lastModifiedDate;
}
  1. 공통적인 속성들을 따로 '추상클래스'에 만들어서 둔다.
  2. 쓰고 싶은 곳에 해당 클래스를 상속만 하면 자동적으로 공통속성이 적용된다.



실전 예제 4. 상속관계 매핑

+) 요구사항 추가

• 상품의 종류는 음반, 도서, 영화가 있고 이후 더 확장될 수 있다.
• 모든 데이터는 등록일과 수정일이 필수


싱글 테이블로 설계 - 단순하게

코드

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
public abstract class Item extends BaseEntity {
    //item을 단독으로 저장할 일이 있냐 없냐 해서-> 없다 가정 추상클래스로 지정
    ...
    }
  • Item 클래스 item을 단독으로 저장할 일이 있냐 없냐 해서-> 없다 가정하여 추상클래스로 지정
  • "DTYPE"으로 지정하지 않아도 JPA가 알아서 지정함.
@Entity
public class Movie extends Item {

    private String director;
    private String actor;
}

@Entity
public class Book extends Item {

    private String author;
    private String isbn;
}

@Entity
public class Album extends Item {

    private String artist;
    private String etc;
}

BaseEntity


@MappedSuperclass
public abstract class BaseEntity {

    private String createdBy;
    private LocalDateTime createdDate;
    private String lastModifiedBy;
    private LocalDateTime lastModifiedDate;
    //getter,setter..
}

강사님의 말씀

이렇게 실전에서 상속관계를 써서 쓸 수 있는 장단점이 있다.
데이터가 억단위로 넘어가면 복잡해지고 그러면 테이블을 단순하게 유지하는 것이 좋기도 하다.
딱 정답은 없다. 우선 처음부터 모든 애플리케이션이 크지 않기에 객체지향적으로 가다가 나중에 필요할때 구조를 변경해주면 된다.

profile
초짜 백엔드 개린이

0개의 댓글