[자바 ORM 표준 JPA 프로그래밍 - 기본편] 07. 고급 매핑

Turtle·2024년 6월 19일
0
post-thumbnail

🙄상속관계 매핑

  • ✔️슈퍼타입 서브타입 논리 모델을 실제 물리 모델로 구현하는 방법
    • 각각 테이블로 변환 → 조인 전략
    • 통합 테이블로 변환 → 단일 테이블 전략
    • 서브타입 테이블로 변환 → 구현 클래스마다 테이블 전략
  • ✔️조인 전략(@Inheritance(strategy = InheritanceType.JOINED))
    • 테이블 정규화
    • 외래 키 참조 무결성 제약조건 활용 가능
    • 저장 공간 효율화
    • 조회시 조인을 많이 사용, 성능 저하
    • 조회 쿼리가 복잡함
    • 데이터 저장시 INSERT 쿼리가 2번 호출됨

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public abstract class Item {
    @Id @GeneratedValue
    private Long id;
    private String name;
    private int price;
}

실행 결과

Hibernate: 
    create table Movie (
        id bigint not null,
        actor varchar(255),
        director varchar(255),
        primary key (id)
    )
Hibernate: 
    create table Book (
        id bigint not null,
        author varchar(255),
        isbn varchar(255),
        primary key (id)
    )
Hibernate: 
    create table Album (
        id bigint not null,
        artist varchar(255),
        primary key (id)
    )
Hibernate: 
    create table Item (
        price integer not null,
        id bigint not null,
        DTYPE varchar(31) not null,
        name varchar(255),
        primary key (id)
    )
  • ✔️단일 테이블 전략(@Inheritance(strategy = InheritanceType.SINGLE_TABLE)))
    • 조인이 필요 없으므로 일반적으로 조회 성능이 빠름
    • 조회 쿼리가 단순함
    • 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다.
    • 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있고 상황에 따라서 조회 성능이 오히려 느려질 수 있다.

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
public abstract class Item {
    @Id @GeneratedValue
    private Long id;
    private String name;
    private int price;
}

실행 결과

Hibernate: 
    create table Item (
        price integer not null,
        id bigint not null,
        DTYPE varchar(31) not null,
        actor varchar(255),
        artist varchar(255),
        author varchar(255),
        director varchar(255),
        isbn varchar(255),
        name varchar(255),
        primary key (id)
    )
  • ✔️구현 클래스마다 테이블 전략(@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS))
    • 데이터베이스 설계자와 ORM 전문가 둘 다 추천하지 않는 전략
    • 서브 타입을 명확하게 구분해서 처리할 때 효과적
    • not null 제약 조건 사용 가능
    • 여러 자식 테이블을 함께 조회할 때 성능이 느려짐
    • 자식 테이블을 통합해서 쿼리하기 어려움

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@DiscriminatorColumn
public abstract class Item {
    @Id @GeneratedValue
    private Long id;
    private String name;
    private int price;
}

실행 결과

Hibernate: 
    create table Movie (
        price integer not null,
        id bigint not null,
        actor varchar(255),
        director varchar(255),
        name varchar(255),
        primary key (id)
    )
Hibernate: 
    create table Album (
        price integer not null,
        id bigint not null,
        artist varchar(255),
        name varchar(255),
        primary key (id)
    )
Hibernate: 
    create table Book (
        price integer not null,
        id bigint not null,
        author varchar(255),
        isbn varchar(255),
        name varchar(255),
        primary key (id)
    )

🙄Mapped Superclass - 매핑 정보 상속

  • ✔️Mapped Superclass - 매핑 정보 상속
    • 공통 매핑 정보가 필요할 때 사용(id, name)
    • 객체들이 주로 사용하는 공통 매핑 정보를 정의
    • 자식 엔티티들은 상속을 통해 BaseEntity의 매핑 정보를 물려받는다.
    • BaseEntity는 테이블과 매핑할 필요가 없고 자식 엔티티에게 공통으로 사용되는 매핑 정보만 제공하면 된다.
    • 부모로부터 물려받은 매핑 정보를 재정의하려면 @AttributeOverrides@AttributeOverride를 사용하고 연관관계를 재정의하려면 @AssociationOverrides@AssociationOverride를 사용한다.
    • 엔티티로 등록한 것이 아니기 때문에 JPQL에서 사용할 수 없고 이 클래스를 직접 생성해서 사용할 일이 거의 없기 때문에 추상 클래스(abstract)로 만드는 것을 권장한다.

@MappedSuperclass
public abstract class BaseEntity {
    @Id @GeneratedValue
    private Long id;
    private String name;
}
@Entity
public class Member extends BaseEntity {
	// ...
}
@Entity
public class Seller extends BaseEntity{
    // ...
}

🙄상속관계 매핑 실전 예제

  • ✔️요구사항 추가
    • 상품의 종류는 음반, 도서, 영화가 있고 이후 더 확장될 수 있다.
    • 모든 데이터는 등록일과 수정일이 필수다.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
public abstract class Item extends BaseEntity {
    @Id @GeneratedValue
    @Column(name = "ITEM_ID")
    private Long id;
    private String name;
    private int price;
    private int stockQuantity;

    @ManyToMany(mappedBy = "items")
    private List<Category> categories = new ArrayList<>();
}
@Entity
public class Album extends Item{
    private String artist;
}
@Entity
public class Book extends Item{
    private String author;
    private String isbn;
}
@Entity
public class Movie extends Item{
    private String director;
    private String actor;
}
@MappedSuperclass
public abstract class BaseEntity {
    private String createdBy;
    private LocalDateTime createdDate;

    private String modifiedBy;
    private LocalDateTime modifiedDate;
}

0개의 댓글