만약 그냥 객체만 고려하여 Item 객체를 만들어 Album, Movie, Book에서 extends Item을 통해 처리해놓고 Item객체에 @Inheritance(strategy = InheritanceType.JOINED)를 걸어주면 아래와 같이 매핑됨.
ex) movie의 경우 movie.setDirector/Actor/Name/Price()해주면 값이 등록된다.
테이블 정규화, 외래 키 참조 무결성 제약조건 활용가능, 저장공간 효율화 같은 장점이 있지만
조회 시 조인을 사용하여 들고오기 때문에 성능저하의 문제와 조회 쿼리가 복잡하고 데이터 저장시 INSERT SQL 2번 호출하여 성능이 좋지 않다.
여기서 @DiscriminatorColumn(name=“DTYPE”)이 어노테이션을 걸어주면? 이 어노테이션이 없을때는 위 ITEM 테이블의 DTYPE 필드가 없을 것이다. 그러나 이 어노테이션을 걸어주면 DTYPE 필드가 아이템 테이블에 추가될 것이고 앨범을 통해 가격과 이름이 추가될 시 Album, 영화면 Movie, 책이면 Book이라고 추가될 것이다. 그래서 쿼리 없이 Item 테이블만 꺼냈을때 이게 어떤 Item을 통해 추가된 row인지 확인할 수 있다.
웬만해서 넣어주는 것이 좋을 것이다!
위에서 DTYPE에 앨범이면 "Album", 영화면 "Movie", 책이면 "Book" 이렇게 들어간다고 했는데 이 Default 값이 각각의 Entity 값일 것인데 이것을 바꾸고 싶다면 @DiscriminatorValue(“XXX”)를 통해 지정해줄 수 있다. 예를들어 Movie 객체에 @DiscriminatorValue("M")이라고 지정해줬다면 Item 객체의 DTYPE 필드 값은 이전에 Movie가 아닌 "M"이 되는 것이다.
2. 통합 테이블로 변환 -> 단일 테이블 전략
조인이 너무 복잡하고 간단한 프로젝트라면? 단일 테이블 전략으로...
만약 그냥 객체만 고려하여 Item 객체를 만들어 Album, Movie, Book에서 extends Item을 통해 상속하면 이렇게 구현된다.
이 @Inheritance(strategy=InheritanceType.XXX) 어노테이션의 Default Value가 SINGLE_TABLE이라 그런 것이다.
조인이 필요 없으므로 쿼리가 항방으로 들어가 일반적으로 조회 성능이 빠르고 조회 쿼리가 단순하다.
그러나 자식 엔티티가 매핑한 컬럼은 모두 null 허용해야하고 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있고 상황에 따라서 조회 성능이 오히려 느려질 수 있다.
3. 서브타입 테이블로 변환 -> 구현 클래스마다 테이블 전략
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)로 해주면 된다.
각 클래스에서 중복되는 필드들이 존재한다.
이 전략은 데이터베이스 설계자와 ORM 전문가 둘 다 추천X
서브 타입을 명확하게 구분해서 처리할 때 효과적이고 not null 제약조건 사용 가능하다. 그러나 여러 자식 테이블을 함께 조회할 때 성능이 느리고(UNION으로 테이블 다 합쳐서 긁어와버려서 비효율적), 자식 테이블을 통합해서 쿼리하기 어렵다.
@MappedSuperclass
귀찮음을 줄이기 위한 장치로 테이블과 관계 없고, 단순히 엔티티가 공통으로 사용하는 매핑 정보를 모으는 역할을 해주는 어노테이션이다.
공통되는 속성을 따로 클래스를 만들어 @MappedSuperclass를 붙혀주고 이 속성이 쓰이는 실제 엔티티들에서 해당 클래스를 상속하여 사용하면 된다.
위와 같이 id, name이라는 공통 속성이 존재할때 그것을 묶어버린다.
이것은 상속관계 매핑이 아니며 실제 엔티티가 아니라 테이블과 매핑되지도 않는다. 따라서 조회, 검색 불가하다.
즉, 부모 클래스를 상속 받는 자식 클래스에 매핑 정보만 제공하며 직접 생성해서 사용할 일이 없으므로 추상 클래스 권장한다.
ex) 등록일, 수정일, 등록자, 수정자
참고 : @Entity 클래스는 엔티티나 @MappedSuperclass로 지 정한 클래스만 상속 가능