#07 고급 매핑

김영한 저 "자바 ORM 표준 JPA 프로그래밍, 2015"을 읽고 정리한 내용입니다.

이 장에서 다룰 고급 매핑

  • 7.1 상속 관계 매핑: 객체의 상속 관계에 대한 데이터베이스 표현

  • 7.2 @MappedSupperClass: 등록일, 수정일 같이 여러 공통으로 사용하는 매핑 정보만 상속받고 싶을때

  • 7.3 복합 키와 식별 관계 매핑: 데이터베이서의 식별자(id) 값이 하나 이상일때 매핑하는 방법

  • 7.4 조인 테이블: 연관관계를 관리하는 연결 테이블(매핑 테이블)을 두는 방법

  • 7.5 엔티티 하나에 여러 테이블을 매핑

7.1 상속 관계 매핑

관계형 데이터베이스에는 상속이라는 개념이 없다. 대신에 아래 그림과 같은 슈퍼타입-서브타입 관계이라는 모델링 기법이 있다.

슈퍼-서브 타입의 논리 모델을 실제 물리 모델인 테이블로 구현할 때는 3가지 방법을 선택할 수 있다.

  • 각각의 테이블로 변환 = JOINED

  • 하나의 테이블로 변환 = SINGLE_TABLE

  • 서브타입 테이블로 변환 = TABLE_PER_CLASS

부모

ITEM

ALBUM

BOOK

MOVIE

7.1.1 조인 전략

조인 전략은 엔티티 각각을 모두 테이블로 만들고 자식 테이블이 부모 테이블의 기본 키를 받아서 기본 키 + 외래 키로 사용하는 전략이다. 타입을 구분하기 위한 컬럼이 필요하다.

@Inheritance(strategy = InheritanceType.JOINED)

만약 자식 테이블의 기본 키 컬럼명을 변경하고 싶다면 @PrimaryKeyJoinColumn을 사용

  • 장점

    • 테이블이 정규화 된다

    • 외래 키 참조 무결성 제약조건을 활용할 수 있다

    • 저장공간을 효율적으로 사용한다

  • 단점

    • 조회할때 성능이 저하될 수 있다

    • 조회 쿼리가 복잡하다

    • 데이터를 등록할때 insert sql이 두 번 실행된다

7.1.2 단일 테이블 전략

테이블 하나를 사용하는 전략

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)

  • 장점

    • 조인이 필요 없으므로, 일반적으로 조회 성능이 빠르다

    • 조회 쿼리가 단순하다

  • 단점

    • 자식 엔티티가 매핑한 컬럼은 모두 NULL 허용해야 한다.

    • 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다

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

각각의 엔티티마다 테이블을 만든다

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)

각각의 자식 엔티티마다 테이블을 만들기 때문에 일반적으로 추천되지 않는다

  • 장점

    • 서브 타입을 구분해서 처리할 때 효과적이다

    • NOT NULL 제약조건을 사용할 수 있다

  • 단점

    • 여러 자식테이블과 함께 조회할 때 성능이 느리다(UNION 사용이 불가피)

    • 자식 테이블을 통합해서 쿼리하기 어렵다

7.2 @MappedSuperclass

부모 클래스는 테이블과 매핑하지 않 자식 클래스에게 매핑 정보만 제공하고 싶을때 사용한다

추상클래스와 비슷하다.(엔티티는 실제 테이블과 매핑된다)

부모로 부터 물려 받은 매핑정보를 재정의 하려면 @AttributeOverride를 사용한다.

특징

  • 테이블과 매핑되지 않고 자식 클래스에 엔티티의 매핑 정보를 상속하기 위해 사용한다.

  • @MappedSuperclass로 지정한 클래스는 엔티티가 아니므로 em.find()나 Jpql에서 사용할 수 없다

  • 직접적으로 생성할일이 적기 때문에 추상클래스로 만드는것이 적합하다

등록일자, 수정일자, 등록자, 수정자와 같은 여러 엔티티를 효율적으로 관리할 수 있다?

  • 등록일시가 필요한 상황

  • 등록일시, 수정일시가 필요한 상황

  • 등록일시, 등록자가 필요한 상황

  • 등록일시, 등록자, 수정일시가 필요한 상황

  • 등록일시, 등록자, 수정일시, 수정자가 필요한 상황

이렇게 요구사항이 다양할 경우 상속 보다는 합성(composition)을 통한 구현이 더 좋지 않을까?

jpa에서 합성은 Embedded objects로 구현되어 있다.

7.3 복합 키와 식별 관계 매핑

7.3.1 식별 관계 vs 비식별 관계

식별 관계

  • 식별 관계는 부모 테이블의 기본 키를 내려받아서 자식테이블의 기본 키 + 외래 키로 사용하는 관계다

비식별 관계

  • 부모의 테이블의 기본 키를 받아서 자식 테이블의 외래키로만 사용하는 관계다.

  • 최근 추세는 비식별 관계를 주로 사용하고 필요한 경우 식별 관계를 사용하는 추세다.

7.3.2 복합 키: 비식별 관계 매핑

둘 이상의 컬럼으로 구성된 복합 기본키 매핑을 위해서 @IdClass@EmbeddedId를 지원한다

@IdClass 사용

  • 식별자 클래스는 필수 조

    • 식별자 클래스의 속성명과 엔티티에서 사용하는 속성명이 같아야 한다.

    • Serializable 인터페이스를 구현해야한다.

    • equals, hashcode를 구현해야한다

@EmbeddedId 사용 - 조금 더 객체지향적인 방법

  • 조건

    • @Embeddable annotation을 붙여주어야 한다.

    • Serializable interface를 구현해야한다

    • equals, hashCode를 구현해야한다.

      • 오버라이딩 하지 않는 다면 == 비교(동일성 비교)를 하기 때문에 의도한대로 동작하지 않을 수 있다

@IdClass vs @EmbeddedId EmbeddId가 더 객체지향적일 수는 있지만 특정 상황에 JPQL이 더 길어질 수 있다.

7.3.3 복합 키: 식별 관계 매핑

부모, 자식, 손자까지 계속 기본 키를 전달하는 관계

이처럼 식별 관계는 기본 키와 외래 키를 같이 매핑해야 한다. 식별자 매핑인 @Id와 연관관계 매핑인 @ManyToOne을 같이 사용하면 된다

@EmbeddedId와 식별 관계

7.3.4 비식별 관계로 구현

7.3.5 일대일 식별 관계

7.3.6 식별, 비식별 관계의 장 단점

일반적으로 비식별 관계를 선호한다.

  • 식별 관계는 2개 이상의 컬럼을 합해서 복합 기본 키를 만들어야 하는 경우가 많다

  • 식별 관계와는 다르게 비즈니스와 전혀 관계 없는 값을 키 값으로 사용한다

  • 테이블 구조가 유연하다

  • 복합 키를 만들기 위해서는 많은 노력이 필요하다

물론 식별 키가 지니는 장점도 있다.

  • 키 인덱스를 활용하기 좋고

  • 특정 상황에서 조인 없이 하위테이블을 조회할 수 있다.

7.4 조인 테이블

데이터베이스에서 테이블간의 연관관계를 설계하는 방법은 크게 2가지다

  • 조인 컬럼 사용(외래 키)

  • 조인 테이블 사용(테이블 사용)

조인 컬럼 사용

  • NULL 값이 허용되 선택적 비식별 관계이다

조인 테이블 사용

  • 조인 테이블의 단점은 테이블을 추가해야된다는 것이다

  • 필요에 따라서 사용하는 것이 좋다

7.4.1 일대일 조인 테이블

@JoinTable속성

  • name : 매핑할 조인 테이블 이름

  • joinColumns : 현재 엔티티를 참조하는 외래 키

  • inverseJoinColumns : 반대방향 엔티티를 참조하는 외래 키

7.4.2 일대다 조인 테이블

7.4.3 다대일 조인 테이블

7.4.4 다대다 조인 테이블

7.5 엔티티 하나에 여러 테이블 매핑

@SecondaryTable보다는 두 테이블을 각각의 엔티티에 매핑후 일대일 연관관계로 만드는 것을 권장한다

Last updated