#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
@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 사용 - 조금 더 객체지향적인 방법
조건
@Embeddableannotation을 붙여주어야 한다.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