- 슈퍼타입 서브타입 논리 모델을 실제 물리 모델인 테이블로 구현할 때는 3가지 방법을 선택할 수 있음.
- 각각의 테이블로 변환: 각각을 모두 테이블로 만들고 조회할 때 조인을 사용한다. jpa에서는 이를 조인전략이라고 한다.
- 통합 테이블로 변환 : 테이블을 하나만 사용해서 통합한다. jpa에서는 단일 테이블 전략이라 한다.
- 서브타입 테이블로 변환 : 서브타입마다 하나의 테이블을 만든다. jpa에서는 구현 클래스마다 테이블 전략이라 한다.
- 엔티티 각각을 모두 테이블로 만들고 자식 테이블이 ㅂ부모 테이블의 기본 키를 받아서 기본키 + 외래키로 사용하는 전략이다.
- @inheritance(strategy = InheritanceYype.JOINED) : 상속 매핑은 부모 클래스에 @Inheritance를 사용해야한다.
- @DiscriminatorColumn(nmae="DTYPE") : 부모클래스에 구분 컬럼을 지정한다. 이 컬럼으로 저장된 자식테이블을 구분할 수 있다. default값은 "DTYPE"
- @DiscriminatorValue("M") : 엔티팉를 저장할 때 구분 컬럼에 입력할 값을 지정한다.
- 기본값으로 자식 테이블은 부모테이블의 ID컬럼명을 그대로 사용하는데, 만약 자식 테이블의 기본 키 컬럼명을 변경하고 싶으면 @primaryKeyJoinColumn을 사용하면 된다.
- 장점 ? 테이블 정규화, 외래 키 참조 무결성 제약조건을 활용할 수 있다. 저장공간을 효율적으로 사용한다.
- 단점 ? 조인쿼리 성능 저하, 조회쿼리가 복잡함. 데이터 등록 ISNERT쿼리 두 번 실행.
- 이름 그대로 테이블을 하나만 사용한다. 구분 컬럼으로 어떤 자식 데이터가 저장되었는지만 구분한다. 조회시 조인사용하지 않으므로 일반적으로 가장 빠름.
- 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야함.
- @inheritanceType.SINGLE_TABLE
- 테이블 하나에 모든 것을 통합하므로 구분 컬럼을 필수로 사용해야함.
- 장점? 조인이 필요없어 조회 성능이 빠름, 조회쿼리 단순
- 단점? 자식 엔티티가 매핑한 컬럼은 모두 null 허용, 테이블 규모 비대해져서 오히려 조회 성능이 나빠질 수도 있음.
- 특징 @DiscriminatorColumn 설정이 필수임.
- 자식엔티티마다 테이블을 만듬. 자식 테이블 각각에 필요한 컬럼이 모두 있음.
- @inheritanceType.TABLE_PER_CLASS
- 일반적으로 추천하지 않음.
- 장점? 서브타입을 구분해서 처리할 때 효과적임, not null 제약조건 사용가능
- 단점? 여러 자식테이블을 함께 조회할때 성능이 느림(UNION), 자식 테이블을 통합해서 쿼리하기 어려움.
- 부모클래스는 테이블과 매핑하지 않고 부모 클래스를 상속 받는 자식 클래스에게 매핑정보만 제공하고 싶을때 사용.
- 추상클래스와 비슷하다. @Entity는 실제 테이블 과 매핑되지만 @MappedSuperClass는 실제 테이블과는 매핑되지 않는다. 단순히 매핑 정보를 상속할 목적으로만 사용된다.
- 따라서 em.find()나 JPQL에서 사용할 수 없음.
- 이 클래스를 직접 생성해서 사용할 일은 없으므로 추상클래스로 만드는 것을 권장한다.
- 부모로 부터 물려받은 매핑정보를 재정의하려면 @AttributeOberride를 사용하고 연관관계를 재정의하려면 @AssociationOverride를 사용한다.
- 정리하자면 @MappedSuperclass는 테이블과는 관계가 없고 단순히 엔티티가 공통으로 사용하는 매핑정보를 모아주는 역할을 할 뿐이다. ORM에서 말하는 진정한 상속매핑이 아님.
- 외래키가 기본키에 포함되는지 여부에 따라 갈림.
- 식별관계 : 부모테이블의 기본키를 내려받아서 자식 테이블의 기본키+외래키로 사용하는 관계
- 비식별관계 : 부모테이블의 기본키를 받아서 자식테이블의 외래키로만 사용하는 관계
- 필수적 비식별관계 : 외래키에 null을 허용하지 않음.
- 선택적 비식별관계 : 외래키에 null을 허용함.
- jpa에서 식별자를 둘 이상 사용하려면 별도의 식별자 클래스를 만들어야함.
- 식별자 클래스의 속성명과 엔티티에서 사용하는 식별자의 속성명이 같아야한다.
- Serializable인터페이스 구현
- equals, hashcode 구현
- 기본 생성자가 있어야한다.
- 식별자 클래스는 public이어야한다.
- @IdClass : 부모에서는 @Id로만 매핑, 자식은 @JoinColumns, referencedColumnNma으로 매핑함.
- @EmbeddedId : 좀더 객체지향적임. 식별자클래스에 @Embeddable 붙여줌. @IdClass와 다르게 식별자 클래스에 기본 키를 직접 매핑함.
- 동등성비교가 아닌 동일성 비교를 위해 equals와 hashcode 재정의는 필수.
- @IdClass vs @EmbeddedId 장단점이 있으니 취향에 따라 선택.
- @IdClass: @Id로 Joined Column을 식별관계로 만듬.
- @EmbeddedId: @MapsId로 Joined Column을 식별관계로 만듬.
- 데이터 베이스 설께관점에서 보면 식별 관계보다는 비식별관계를 선호함.
-
- 식별 관계는 부모 -> 자식으로 기본 키가 전파되면서 기본 키 컬럼이 점점 늘어난다. 결국 조인할때 sql이 복잡해지고 기본 키 인덱스가 불필요하게 커질 수 있음.
-
- 식별관계는 2개 이상의 컬럼을 합해서 복합 기본 키를 만들어야 하는 경우가 많음.
-
- 식별관계 사용시에 기본 키로 비즈니스 의미가 있는 자연 키 컬럼을 조합하는 경우가 많음. 반면 비식별 관계의 기본 키는 대리 키를 주로 사용. 비즈니스는 유동적임. 식별관계의 자연 키 컬럼들이 자식에 손자까지 전파되면 변경이 어려움.
-
- 식별관계는 부모 테이블의 기본 키를 자식테이블의 기본 키로 사용하므로 비식별 관계보다 테이블 구조가 유연하지 못함.
-
- 복합키를 객체지향에서 사용하려면 별도의 클래스를 만들어야하므로 경제적이지 못함.
-
- 비식별관계는 대리키를 주로 사용하는데 JPA는 대리키 자동생성 가능해서 편함.
-
- 식별관계의 장점
- 기본 키 인덱스를 활용하기 좋음.
- 상위 테이블들의 기본 키를 자식들이 가지고 있으므로 특정상황에 조인 없이 하위 테이블만으로 검색할 수 있음.
- 그러나 추천하는 방법은 비식별관계를 사용하고 기본 키는 Long 타입(Integer는 부족함.)의 대리 키를 사용하는 것.
- 선택적 비식별 관계보다는 필수적 비식별 관계를 사용하는 것이 좋음. OuterJoin, innerJoin에 대한 차이.
- 일대다 관계를 만들려면 조인 테이블의 컬럼 중 다와 관련된 컬럼인 CHILD_ID에 유니크 제약조건을 걸어야한다.
- 일대다와 반대로...
- 조인 테이블의 두 컬럼을 합해서 하나의 복합 유니크 제약조건을 걸어야한다. 다대다 조인 테이블 매핑
- 잘 사용하지는 않지만 @SecondaryTable을 사용하면 하나의 엔티티에 여러 테이블을 매핑할 수 있음.