일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Java
- git
- graphql
- nginx
- GCM 번역
- GCM
- 웹사이트성능
- 성능
- 카프카 트랜잭션
- nginx설치
- 디자인패턴
- 카프카
- 푸시
- gcm 푸시 번역
- ddd
- Push
- Design Pattern
- 웹사이트 성능
- nginx설정
- notification
- APNS
- JPA
- 도메인 주도 개발
- 페이스북 번역
- 푸시 번역
- kafka
- 자바스크립트
- php
- 웹사이트최적화기법
- Today
- Total
간단한 개발관련 내용
7장 고급 매핑 본문
7.1 상속 관계 매핑
- supertype subtype Relationship
- 각각의 테이블로 변환
- 조인전략
- 통합 테이블로 변환
- 단일 테이블 전략
- 서브타입 테이블로 변환
- 구현 클래스마다 테이블 전략
- 각각의 테이블로 변환
7.1.1 조인 전략
- 부모테이블의 키를 받아서 기본키 + 외래키 복합키를 갖게 된다
- 장점
- 테이블이 정규화된다
- 외래키 참조 무결성 제약 조건을 사용할 수 있다
- 저장 공간을 효율적으로 사용할 수 있다
- 단점
- 조회할 때 조인이 많이 사용되므로 성능이 저하될 수 있다
- 조회 쿼리가 복잡하다
- 데이터를 등록할 때 INSERT SQL을 두 번 실행한다.
7.1.2 단일 테이블 전략
- 구분칼럼(DTYPE)으로 어떤 자식 데이터가 저장되었는지 구분한다
- 장점
- 조인이 필요없으므로 일반적으로 조회 성능이 빠르다
- 조회 쿼리가 단순하다
- 단점
- 구분 칼럼을 꼭 사용해야 한다
- 따라서 @DiscriminationColumn을 꼭 설정해야 한다
- @DiscriminatorValue를 지정하지 않으면 기본으로 엔터티 이름을 사용한다
7.1.3 구현 클래스마다 테이블 전략
- Table-per-Concrete-Class Strategy
- 자식 엔터티마다 테이블을 만든다
- 장점
- 서브 타입을 구분해서 처리할 때 효과적이다
- not null 제약조건을 사용할 수 있다
- 단점
- 여러 자식 테이블을 함께 조회할 때 성능이 느리다.(SQL에 UINION을 사용해야 한다)
- 자식 테이블을 통합해서 쿼리하기 어렵다
- 특징
- 구분 컬럽을 사용하지 않는다
7.2 @MappedSuperclass
- 테이블과 매핑되지 않고 자식 클래스에 엔터티의 매핑 정보를 상속하기 위해 사용한다
- @MappedSuperclass로 지정한 클래스는 엔터티가 아니므로 em.find()나 JPQL에서 사용할 수 없다
- 이 클래스를 직접 생성해서 사용할 일은 거의 없으므로 추상 클래스로 만드는 것을 권장한다
- 정리하자면 @MappedSuperclass는 테이블과는 관계가 없고 단순히 엔터티가 공통으로 사용하는 매핑정보를 모아주는 역할을 할 뿐이다
- 생성일, 수정일 같은 공통 필드 모음
7.3 복합 키와 식별관계 매핑
7.3.1 식별관계 vs 비식별관계
- 데이터베이스 테이블 사이에 관계는 외래 키가 기본 키에 포함되는지 여부에 따라 식별 관계와 비식별 관계로 구분한다. 두 관계의 특징을 이해하고 각각을 어떻게 매핑하는지 알아보자.
- 식별관계(Identifying RelationShip)
- 부모테이블의 기본키를 내려받아서 자식 테이블의 기본 키 + 외래 키로 사용하는 관계다
- PARENT_ID 가 기본키(PK) + 외래키(FK)로 사용
- 인덱스로 찾이게 좋다
- 비식별관계(Non-Identifying RelationShip)
- 부모 테이블의 기본 키를 받아서 자식 테이블의 외래 키로만 사용하는 관계다
- 필수적 비식별관계
- 외래 키에 NULL을 허용하지 않는다. 연관관계를 필수적으로 맺어야한다.
- 선택적 비식별관계
- 외래 키에 NULL을 허용한다. 연관관계를 맺을지 말지 선택할 수 있다.
<aside> 💡
최근에는 비식별 관계를 주로 사용하고 꼭 필요한 곳에만 식별관계를 사용하는 추세다
</aside>
7.3.2 복합키 : 비식별관계 매핑
- JPA는 영속성 컨텍스트에 엔터티를 보관할 때 엔터티의 식별자를 키로 사용한다. 그리고 식별자를 구분하기 위해 equals와 hashCode를 사용해서 동등성 비교를 한다. 그런데 식별자 필드가 하나일때는 보통 자바의 기본 타입을 사용하므로 문제가 없지만, 식별자 필드가 2개 이상이면 별도의 식별자 클래스를 만들고 그곳에 equals와 hashCode를 구현해야 한다.
- 복합키를 지원하기 위해
- @IdClass와 @EmbeddedId 2가지 방법을 제공한다
- @IdClass 는 데이터베이스에 맞춘 방법
- @EmbeddedId 는 객체지향 스러운 방법
7.3.3 복합키 : 식별관계 매핑
7.3.4 비식별관계로 구현 (266p)
7.3.5 일대일 식별 관계 (268p)
- 일대일 식별 관계는 자식 테이블의 기본 키 값으로 부모 테이블의 기본 키 값만 사용한다
7.3.6 식별, 비식별 관계의 장단점
데이터베이스 설계 관점에서 보면 다음과 같은 이유로 식별 관계보다는 비식별 관계를 선호한다
- 식별관계는 부모 테이블의 기본 키를 자식 테이블로 전파하면서 자식 테이블의 기본 키 칼럼이 점점 늘어난다. 예를 들어 부모 테이블은 기본 키 컬럼이 하나였지만 자식 테이블은 기본 키 컬럼이 2개, 손자 테이블은 기본 키 컬럼이 3개로 점점 늘어난다. 결국 조인할 때 SQL이 복잡해지고 기본 키 인덱스가 불필요하게 커질 수 있다.
- 식별관계는 2개 이상의 컬럼을 합해서 복합 기본 키를 만들어야 하는 경우가 많다.
- 식별관계를 사용할 때 기본 키로 비즈니스 의미가 있는 자연 키 컬럼을 조합하는 경우가 많다. 반면에 비식별 관계의 기본 키는 비즈니스와 전혀 관계없는 대리 키를 주로 사용한다. 비즈니스 요구사항은 시간이 지남에 따라 언젠가는 변한다. 식별관계의 자연 키 컬럼들이 자식에 손자까지 전파되면 변경하기 힘들다.
- 식별관계는 부모 테이블의 기본 키를 자식 테이블의 기본 키로 사용하므로 비식별 관계보다 테이블 구조가 유연하지 못하다.
객체 관계 매핑의 관점에서 보면 다음과 같은 이유로 비식별 관계를 선호한다.
- 일대일 관계를 제외하고 식별관계는 2개 이상의 칼럼을 묶은 복합 기본 키를 사용한다. JPA에서 복합 키는 별도의 복합 키 클래스를 만들어서 사용해야 한다. 따라서 컬럼이 하나인 기본 키를 매핑하는 것보다 많은 노력이 필요하다.
- 비식별 관계의 기본 키는 주로 대리 키를 사용하는데 JPA는 @GenerateValue처럼 대리 키를 생성하기 위한 편리한 방법을 제공한다.
7.4 조인테이블
- 조인 컬럼 사용(외래 키: 비식별관계)
- 필수적 비식별관계
- 선택적 비식별관계 : 외래 키가 null이라 outter join 필요
- 조인 테이블 사용(테이블 사용)
- 조인 테이블이라는 별도의 테이블을 사용해서 연관관계를 관리한다
- 다대다 관계를 일대다, 다대일 관계로 풀어내기 위해 사용
7.4.1 일대일 조인 테이블
7.4.2 일대다 조인 테이블
7.4.3 다대일 조인 테이블
7.4.4 다대다 조인 테이블
7.5 엔터티 하나에 여러 테이블 매핑
- @SecondaryTable을 사용해서 1개이상의 테이블을 하나의 엔터티에 매핑할 수 있다
7.6 정리
실전 예제 | 4. 상속 관계 매핑
상속관계 매핑은 잘 안 쓰는 것 같은데 반드시 써야하는 경우가 있을까
JPA의 상속관계 매핑은 객체 지향 프로그래밍에서 상속을 활용하여 공통된 속성과 메서드를 여러 엔티티에서 공유할 수 있도록 해주는 기능입니다. 이러한 상속관계 매핑은 특정 상황에서 유용하게 사용될 수 있지만, 모든 경우에 반드시 필요한 것은 아닙니다. 사용해야 하는 경우와 그렇지 않은 경우를 구분해보면 다음과 같습니다.
상속관계 매핑을 사용하는 경우
- 유사한 엔티티 간의 공통 속성과 메서드 공유
- 여러 엔티티가 비슷한 속성을 공유할 때, 코드 중복을 줄이고 유지 보수를 용이하게 하기 위해 상속관계를 사용합니다.
- 예: Employee, Manager, Intern 같은 엔티티가 모두 Person이라는 부모 클래스를 상속받아 공통 속성(이름, 연락처 등)을 공유할 수 있습니다.
- 다형성 활용
- 특정 엔티티 타입에 따라 다르게 처리해야 할 때 유용합니다. 부모 타입을 사용하여 여러 자식 타입의 객체를 동일한 컨텍스트에서 다룰 수 있습니다.
- 예: Vehicle 클래스를 상속받은 Car, Bike 엔티티를 관리할 때, Vehicle 타입의 리스트에서 다양한 차량을 처리할 수 있습니다.
- 데이터베이스의 데이터 정규화
- 상속을 통해 데이터베이스의 테이블 구조를 정규화할 수 있습니다. 자주 사용되는 속성을 부모 테이블에 두고, 특화된 속성은 자식 테이블에 두어 데이터를 효율적으로 저장할 수 있습니다.
- 복잡한 비즈니스 로직
- 상속을 통해 비즈니스 로직을 분리하고, 각 엔티티에 맞게 특화된 동작을 정의할 수 있습니다. 예를 들어, 특정 조건에 따라 다양한 엔티티에서 서로 다른 동작을 수행할 수 있습니다.
상속관계 매핑을 사용하지 않는 경우
- 단순한 모델
- 도메인 모델이 간단하고, 상속을 사용해도 실제로 이점이 없는 경우에는 굳이 상속관계를 설정할 필요가 없습니다. 불필요한 복잡성을 초래할 수 있습니다.
- 유지 보수의 어려움
- 상속을 사용할 경우, 상위 클래스의 변경이 하위 클래스에 영향을 미칠 수 있어, 유지 보수가 복잡해질 수 있습니다. 코드 변경이 있을 때, 모든 관련 클래스를 검토해야 하는 번거로움이 생깁니다.
- JPA의 성능 고려
- JPA의 상속 매핑은 성능에 영향을 미칠 수 있습니다. 특히, 전략에 따라 조인 테이블을 사용하거나 서브타입을 관리해야 할 경우, 성능 저하가 발생할 수 있습니다.
- 특정 데이터베이스 지원 제한
- 일부 데이터베이스에서는 상속관계 매핑을 지원하지 않거나 제한적인 방식으로 지원할 수 있습니다. 이러한 경우에는 상속관계를 사용하는 것이 비효율적일 수 있습니다.
결론
JPA의 상속관계 매핑은 특정 도메인 모델이 복잡하거나, 공통 속성을 가지는 여러 엔티티를 관리해야 할 때 유용합니다. 그러나 모든 경우에 반드시 필요한 것은 아니며, 단순한 모델이나 유지 보수의 복잡성을 고려할 때는 피하는 것이 좋습니다. 적절한 사용은 비즈니스 로직과 데이터베이스 구조를 고려하여 결정해야 합니다.
페이지 요약
상속 관계 매핑
- 상속 관계 매핑에는 조인 전략, 단일 테이블 전략, 구현 클래스마다 테이블 전략이 있다
- 조인 전략은 정규화된 테이블을 사용하지만 조회 시 조인으로 인한 성능 저하가 발생할 수 있다
- 단일 테이블 전략은 조회 성능이 빠르지만 구분 칼럼을 반드시 사용해야 한다
- 구현 클래스마다 테이블 전략은 서브타입을 명확히 구분할 수 있지만 여러 자식 테이블을 함께 조회할 때 성능이 느리다
@MappedSuperclass
- @MappedSuperclass는 테이블과 관계없이 공통 매핑 정보를 모아주는 역할을 한다
복합 키와 식별 관계
- 식별 관계는 부모 테이블의 기본 키를 자식 테이블의 기본 키로 사용하는 관계이다
- 비식별 관계는 부모 테이블의 기본 키를 외래 키로만 사용하는 관계이다
- 최근에는 비식별 관계를 주로 사용하고 필요한 경우에만 식별 관계를 사용하는 추세이다