본문 바로가기
JAVA/JPA

[Spring + JPA] JPA 상속관계 매핑

by 개미가되고싶은사람 2024. 11. 12.

목차

    상속관계 매핑

    관계형 데이터베이스는 상속 관계 기능이 없지만, 슈퍼타입-서브타입 관계를 통해 유사한 개념을 구현할 수 있습니다. 슈퍼타입은 공통 속성(칼럼)을 가진 상위 개념을 나타내고, 서브타입은 슈퍼타입 속성을 공통적으로 가지고 개별적인 속성(칼럼)을 가질 수 있습니다. 예를 들어, '직원'이라는 슈퍼타입이 있을 때, '인사 부서'와 '마케팅 부서'는 각각의 서브타입으로, 서브타입들은 '직원'의 속성을 가지면서 각기 다른 특성을 가질 수 있습니다.

     

     

    이제부터 슈퍼 타입을 부모 테이블으로 부르고, 서브 타입을 자식 테이블이라고 말하겠습니다.

     

     

    상속관계 매핑 전략

    1. 조인전략 - JOINED

    조인 전략은 부모 클래스와 자식 클래스 각각에 대해 별도의 테이블을 생성하고, 이들 테이블 간의 관계를 조인하여 데이터를 조회하는 방식으로, 이때 자식 테이블은 부모 테이블의 기본키를 받아서 기본키 + 외래키로 사용합니다. 이로 인해 자식 테이블에 데이터를 추가할 때는 부모 테이블의 기본키를 사용해야 하므로 부모 테이블과 자식 테이블에 각각 두 번의 insert 쿼리가 실행됩니다.

     

    @Entity
    @Inheritance(strategy = InheritanceType.JOINED) // 해당 속성만 변경해서 원하는 전략을 사용하면 됩니다
    @DiscriminatorColumn
    public class Item {
    
        @Id
        @GeneratedValue
        @Column(name = "ITEM_ID")
        private Long id;
    
        private String name;
        private Integer price;
    }
    
    @Entity
    @DiscriminatorValue("M")
    public class Movie extends Item {
        private String director;
        private String actor;
    }
    
    @Entity
    @DiscriminatorValue("B")
    public class Book extends Item {
        private String author;
        private String isbn;
    }
    
    @Entity
    @DiscriminatorValue("A")
    public class Album extends Item{
        private String artist;
    }

     

     

    장점 및 단점

     

    장점

    • 테이블이 정규화 할 수 있습니다.
    • 외래키 참조 무결성 제약조건을 활용할 수 있습니다.
    • 저장공간이 효율화 ↑

    단점

    • 자식 테이블 조회 시 조인이 필요하기 때문에 성능이 떨어질 수 있습니다.
    • 자식 테이블 조회 시 일 테이블 전략에 비해 조회 쿼리가 복잡합니다
    • 자식 테이블 저장시 INSERT 쿼리가 2번 호출됩니다.

    추가적으로 자식 테이블을 조회할 때 inner조인이 실행 된다는데 이 이유에 대해서 잘 아시는 분 알려주시면 감사하겠습니다 ㅠㅠ

    2. 단일 테이블 전략 - SINGLE_TABLE

    단일 테이블 전략은 이름 그대로 하나의 테이블만을 사용하며, 이때 @DiscriminatorColumn을 활용하여 어떤 데이터가 저장되었는지를 구분할 수 있는 방식입니다. 그리고 이 전략은 JPA의 기본 전략입니다.

     

    장점 및 단점

     

    장점

    • 조인이 필요 없기 때문에 일반적인 상황에서 조회 성능이 빠르다.
    • 데이터 등록 시 INSERT 쿼리가 1번만 나갑니다.
    • 테이블 구조가 단순하고 관리하기 쉽습니다.

    단점

    • 자식 엔티티에 매핑한 컬럼은 모두 null을 허용해야 합니다
    • 테이블의 컬럼이 많아지고, 레코드 갯수가 많아지기 때문에 상황에 따라 조회 성능이 오히려 느려질 수 있습니다.

     

    3. 구현 클래스마다 테이블 전략(TABLE_PER_CLASS) - 일반적으로 사용 x

    자식 테이블의 개수만큼 테이블을 생성하는 전략으로, 각 자식 테이블은 부모 테이블에 있는 공통 속성을 공유하며, 자식 테이블의 특징에 맞춰 각기 다른 속성을 갖는 방식입니다. 해당 전략은 조회 시 UNION ALL을 사용하기 때문에 성능이 매우 느릴 수 있으니 데이터베이스 설계자와 ORM전문가 둘 다 추천하지 않는 전략입니다.

    주요 애노테이션

    상속관계 매핑에는 주로 해당 애노테이션이 사용됩니다.

    • @Inheritance(strategy=InheritanceType.XXX): 상속관계 매핑 방법을 선 (JOINED, SINGLE_TABLE, TABLE_PER_CLASS)
    • @Discrimintaorcolumn(name="xxx"): 부모 클래스에서 자식 클래스를 구분하는 컬럼의 이름을 설정(기본값 DTYPE)
    • @DiscriminatorValue("XXX"): 자식 클래스를 식별하기 위해 부모의 DTYPE 컬럼에 저장될 값을 설정(기본 값은 클래스 이름)

    공통 속성 - @MappedSuperclass

    여러 엔티티에서 공통으로 사용하는 속성을 재사용 할 수 있게 해주는 애노테이션입니다.

    상속관계 매핑과 헷갈리면 안됩니다. 상속관계 매핑처럼 상위 클래스 물품(Item) 타입에 하위 클래스 앨범(Album)을 종속시키는 것이 아닙니다. 단순히 공통 속성들만 재사용하기 위해 상속을 사용하는 것입니다. 상위 클래스는 엔티티가 아니고 자식 클래스에 속성만 물려줍니다. 엔티티가 아니기 때문에 당연히 상위 클래스로 조회, 검색 할 수 없다. 상위 클래스는 공통 속성의 모음일 뿐 객체화할 일이 없기 때문에 추상 클래스로 만들 것을 권장합니다.

     

     

    속성 이름 재정의 - @AttributeOverride

    @MappedSuperclass
    public abstract class BaseEntity {
    
        @Id @GeneratedValue
        private Long id;
        private String name;
    }
    
    // 속성 한 개만 변경할 때
    @Entity
    @AttributeOverride(name = "id", column = @Column(name = "MEMBER_ID"))
    public class Member extends BaseEntity{
    
        private String email;
    }
    
    
    // 속성 여러 개 변경할 때
    @Entity
    @AttributeOverrides({
            @AttributeOverride(name = "id", column = @Column(name = "MEMBER_ID")),
            @AttributeOverride(name = "name", column = @Column(name = "MEMBER_NAME"))
    })
    public class Member extends BaseEntity {
    
        private String email;
    }

     

     

    출저

    https://velog.io/@imcool2551/JPA-%EC%83%81%EC%86%8D%EA%B4%80%EA%B3%84-%EB%A7%A4%ED%95%91

    https://brightstarit.tistory.com/52

    https://hstory0208.tistory.com/entry/JPA-%EC%83%81%EC%86%8D%EA%B4%80%EA%B3%84-%EB%A7%A4%ED%95%91-%EB%A7%A4%ED%95%91-%EC%A0%95%EB%B3%B4-%EC%83%81%EC%86%8D%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90

    https://devjaewoo.tistory.com/134#%EC%A3%BC%EC%9A%94_%EC%96%B4%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98