7장 고급 매핑
7.1 상속 관계 매핑
∘ 관계형 데이터베이스에는 객체지향 언어에서의 상속과 같은 개념이 없음
∘ ORM에서의 상속 관계 매핑은 객체의 상속 구조와 데이터베이스의 슈퍼타입 서브타입 관계를 매핑하는 것
∘ 슈퍼타입 서브타입 논리 모델을 실제 물리 모델 테이블로 구현하는 방법
- 각각의 테이블로 변환 : 각각을 모두 테이블로 만들고 조인 사용해서 조회. 조인 전략.
- 통합 테이블로 변환 : 테이블 하나만 사용해서 통합. 단일 테이블 전략.
- 서브타입 테이블로 변환 : 서브 타입마다 하나의 테이블 만듦. 구현 클래스마다 테이블 전략.
7.1.1 조인 전략
∘ 조인 전략 : 엔티티 각각을 모두 테이블로 만들고 자식 테이블이 부모 테이블의 기본 키를 받아서 기본 키 + 외래 키로 사용
∘ 테이블의 타입을 나타낼 수 있는 컬럼 필요
∘ 자식 테이블의 기본 키 컬럼명은 @PrimaryKeyJoinColumn을 사용해서 변경할 수 있음
∘ 장점
- 테이블이 정규화됨
- 외래 키 참조 무결성 제약조건을 활용할 수 있음
- 저장공간을 효율적으로 사용함
∘ 단점
- 조회할 때 조인이 많이 사용되어 성능이 저하될 수 있음
- 조회 쿼리가 복잡함
- 데이터를 등록할 INSERT SQL을 두 번 실행
∘ 관련 어노테이션 : @PrimaryKeyJoinColumn, @DiscriminatorColumn, @DiscriminatorValue
7.1.2 단일 테이블 전략
∘ 구분 컬럼(DTYPE)으로 어떤 자식 데이터가 저장되었는지 구분
∘ 조회할 때 조인을 사용하지 않아서 일반적으로 가장 빠름
∘ 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 됨
∘ 장점
- 일반적으로 조회 성능 좋음
- 조회 쿼리가 단순함
∘ 단점
- 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 함
- 테이블이 한 개이므로 테이블이 커질 수 있음
∘ 구분 컬럼을 꼭 사용해야 함 = @DiscriminatorColumn을 필수로 설정해야 함
7.1.3 구현 클래스마다 테이블 전략
∘ 자식 엔티티마다 테이블을 만듦
∘ 장점
- 서브 타입을 구분해서 처리할 때 효과적
- not null 사용할 수 없음
∘ 단점
- 여러 자식 테이블을 함께 조회할 때 성능이 안 좋음
- 자식 테이블을 통합해서 쿼리하기 어려움
∘ 구분 컬럼을 사용하지 않음
7.2 @MappedSuperClass
∘ 실제 테이블과 매핑되지 않음. 매핑 정보를 상속할 목적으로만 사용됨.
∘ 부모로부터 물려받은 매핑 정보 재정의 : @AttributeOverrides, @AttributeOverride
∘ 연관관계 재정의 : @AssociationOverrides, @AssociationOverride
∘ @MappedSuperclass로 지정한 클래스는 엔티티가 아니므로 em.find()나 JPQL에서 사용할 수 없음
∘ 이것보다 추상 클래스로 만드는 것을 권장
7.3 복합 키와 식별 관계 매핑
7.3.1 식별 관계 VS 비식별 관계
∘ 데이터베이스 테이블 사이에 관계는 외래 키가 기본 키에 포함되는지 여부에 따라 식별 관계, 비식별 관계로 구분됨
∘ 식별 관계 : 부모 테이블의 기본 키를 내려받아서 자식 테이블의 기본 키 + 외래 키로 사용하는 관계
∘ 비식별 관계 : 부모 테이블의 기본 키를 받아서 자식 테이블의 외래 키로만 사용하는 관계
- 필수적 비식별 관계 : 외래 키에 NULL을 허용하지 않음. 연관관계를 필수적으로 맺어야 함.
- 선택적 비식별 관계 : 외래 키에 NULL을 허용함. 연관관계를 맺을지 말지 선택 가능.
∘ 일반적으로 주로 비식별 관계를 사용하고 꼭 필요한 곳에만 식별관계 사용
7.3.2 복합 키: 비식별 관계 매핑
∘ 두 개 이상의 식별자를 사용하려면 별도의 식별자 클래스를 만들어야 함
∘ 별도의 식별자 클래스에 equals, hashCode 구현해야 됨
∘ @IdClass
- PARENT 테이블의 기본 키가 복합 키로 구성되어 있으므로 복합 키 매핑을 위해 식별자 클래스 생성 필요
- 각각의 기본 키 컬럼에 @Id → ParentId 클래스에 @IdClass
- @IdClass를 적용한 식별자 클래스
- 식별자 클래스의 속성명과 엔티티에서 사용하는 식별자의 속성명이 같아야 함
- Serializable 인터베이스 구현 필요
- equals, hashCode 구현 필요
- 기본 생성자 있어야 함
- 식별자 클래스는 public이어야 함
∘ @EmbeddedId
- @IdClass보다 객체지향적인 방법
- Parent 엔티티에서 식별자 클래스를 직접 사용하고 @EmbeddedId를 적으면 됨
- @EmbeddedId를 적용한 식별자 클래스
- @Embeddable을 붙여야 됨
- Serializable 인터페이스 구현 필요
- equals, hashCode 구현 필요
- 식별자 클래스는 public
∘ 복합 키와 equals(), hashCode()
- 식별자 객체의 동등성 보장을 위해 복합 키는 equals(), hashCode()를 필수로 구현해야 됨
∘ @IdClass vs @EmbeddedId
- @EmbeddedId이 더 객체지향적이고 중복이 없지만 특정 상황에서 JPQL이 조금 더 길 수 있음
7.3.3 복합 키: 식별 관계 매핑
∘ 식별 관계에서 자식 테이블은 부모 테이블의 기본 키를 포함해서 복합 키를 구성해야 하므로 @IdClass나 @EmbeddedId를 사용해서 식별자를 매핑 해야 됨
∘ @IdClass와 식별 관계
- 기본 키와 외래 키를 같이 매핑해야 하므로 식별자 매핑 @Id와 연관관계 매핑 @ManyToOne을 같이 사용
∘ @EmbeddedId와 식별 관계
- @MapsId 사용
7.3.4 비식별 관계로 구현
∘ 식별 관계와 비교해보면 매핑이 쉽고 코드가 단순함
7.3.5 일대일 식별 관계
∘ 일대일 식별 관계는 자식 테이블의 기본 키 값으로 부모 테이블의 기본 키 값만 사용
⇒ 부모 테입르의 기본 키가 복합 키가 아니면 자식 테이블의 기본 키는 복합 키로 구성하지 않아도 됨
∘ 식별자가 컬럼 한 개면 @MapsId를 사용하고 속성 값 비워두면 됨
7.3.6 식별, 비식별 관계의 장단점
∘ 식별 관계는 부모 테이블의 기본 키를 자식 테이블로 전파하면서 자식 테이블의 기본 키 컬럼이 점점 늘어남
∘ 식별 관계는 2개 이상의 컬럼을 합해서 복합 기본 키를 만들어야 하는 경우가 많음
∘ 식별 관계를 사용할 때 기본 키로 비즈니스 의미가 있는 자연 키 컬럼을 조합하는 경우가 많음 ↔ 비식별
∘ 식별 관계는 비식별 관계보다 테이블 구조가 유연하지 못함
∘ 일대일 관계를 제외하고는 식별 관계는 노력이 더 필요함
∘ 비식별 관계는 JPA에서 대리 키 생성을 위한 편리한 방법 제공
7.4 조인 테이블
∘ 조인 컬럼 사용 : 외래 키 컬럼 사용해서 관리
∘ 조인 테이블 사용 : 별도의 테이블을 사용해서 연관관계 관리
∘ 기본적으로는 조인 컬럼 사용
∘ 객체와 테이블을 매핑할 때 조인 컬럼은 @JoinColumn으로 매핑, 조인 테이블은 @JoinTable로 매핑
∘ 조인 테이블은 주로 다대다를 일대다, 다대일로 풀 때 사용
7.4.1 일대일 조인 테이블
7.4.2 일대다 조인 테이블
7.4.3 다대일 조인 테이블
7.4.4 다대다 조인 테이블
7.5 엔티티 하나에 여러 테이블 매핑
∘ @SecondaryTable
- 속성 : name, pkJoinColumns
∘ 더 많은 테이블을 매핑하려면 @SecondaryTables 사용
∘ 테이블당 엔티티를 각각 만들어서 일대일 매핑하는 것을 권장
- 원하는 부분만 조회 가능
7.3 복합 키와 식별 관계 매핑
7.3.1 식별 관계 vs 비식별 관계
∘ 식별 관계 : 부모 테이블의 기본 키를 내려받아서 자식 테이블의 기본 키 + 외래키로 사용하는 관계
∘ 비식별 관계 : 부모 테이블의 기본 키를 받아서 자식 테이블의 외래 키로만 사용하는 관계
- 필수적 비식별 관계 : 외래 키에 Null 허용
- 선택적 비식별 관계 : " 불허
7.3.2 복합 키: 비식별 관계 매핑
∘ JPA에서 식별자를 둘 이상 사용하려면 별도의 식별자 클래스 생성 필요
- 식별자 클래스에 equals와 hashCode 구현 필요
∘ @IdClass를 사용할 때의 식별자 클래스
- 식별자 클래스의 속성명과 엔티티에서 사용하는 식별자의 속성명이 같아야 함
∘ @EmbeddedId의 식별자 클래스
- @Embeddable을 붙여줘야 함
- Serializable 인터페이스 구현 필요
- equals, hashCode 구현 필요
- 기본 생성자 있어야 함
- public이어야 함
7.3.3 복합 키: 식별 관계 매핑
∘ @IdClass
- 기본 키와 외래 키를 같이 매핑해야 하므로 @Id와 @ManyToOne을 같이 사용
∘ @EmbeddedId
- @MapsId 사용
7.3.4 비식별 관계로 구현
7.3.5 일대일 식별 관계
7.3.6 식별, 비식별 관계의 장단점
∘ 데이터베이스 설계 관점에서는 비식별 관계가 더 선호됨
∘ 식별 관계는 자식 테이블의 기본 키 컬럼이 점점 늘어남
∘ 식별 관계는 2개 이상의 컬럼을 합해서 복합 기본 키를 만들어야 하는 경우가 많음
∘ 식별 관계의 자연 키 컬럼이 많이 전파되면 변경이 어려움
7.4 조인 테이블
∘ 조인 컬럼 사용
∘ 조인 테이블 사용
7.4.1 일대일 조인 테이블
∘ 조인 테이블의 외래 키 컬럼 각각에 총 2개의 유니크 제약 조건을 걸어야 함
∘ @JoinTable 사용
7.4.2 일대다 조인 테이블
∘ 조인 테이블의 컬럼 중 다(N)와 관련된 컬럼에 유니크 제약 조건을 걸어야
7.5 엔티티 하나에 여러 테이블 매핑
∘ @SecondaryTable을 사용하여 한 엔티티에 여러 테이블 매핑 가능
∘ @SecondaryTable을 사용하면 항상 두 테이블을 조회하기 때문에 최적화가 어려움
=> @SecondaryTable을 사용해서 두 테이블을 하나의 엔티티에 매핑하는 것보다 테이블당 엔티티를 각각 만들어서 일대일 매핑하는 것이 권장됨
'Back-End > 자바 ORM 표준 JPA 프로그래밍' 카테고리의 다른 글
[JPA] 자바 ORM 표준 JPA 프로그래밍_9장 (0) | 2023.06.27 |
---|---|
[JPA] 자바 ORM 표준 JPA 프로그래밍_6장 (0) | 2023.06.20 |
[JPA] 자바 ORM 표준 JPA 프로그래밍_5장 (0) | 2023.06.05 |
[JPA] 자바 ORM 표준 JPA 프로그래밍_4장 (0) | 2023.05.29 |
[JPA] 자바 ORM 표준 JPA 프로그래밍_3장 (0) | 2023.05.29 |