[DB] 테이블을 설계하자! -3
1. 조인전략
엔터티 각각을 테이블로 만들고 자식 테이블이 부모 테이블의 기본키를 받아서 pk+fk로 사용한다.
*주의 :객체는 타입으로 구분할 수 있지만 테이블은 타입의 개념이 없어서
Dtype 컬럼과 같이 타입을 구분하는 컬럼이 있어야함
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item {
@Id
@GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
private String name;
private int price;
}
@Entity
@DiscriminatorValue("A")
public class Album extends Item {
private String artist;
}
@Entity
@DiscriminatorValue("M")
public class Movie extends Item {
private String director;
private String actor;
}
@Entity
@DiscriminatorValue("B")
@PrimaryKeyJoinColumn(name = "BOOK_ID")
public class Book extends Item {
private String author;
private String isbn;
}
@inheritance
상속 매핑은 부모 클래스에 @Inheritance를 사용해야 한다. 그리고 매핑 전략을 지정하기 위해 InheritanceType.JOINED를 사용하였다.
@DiscriminatorColumn
부모 클래스에 구분 컬럼을 지정한다. 이 컬럼으로 저장된 자식 테이블을 구분할 수 있으며, 기본 값은 "DTYPE"이다.
@DiscriminatorValue
엔티티를 저장할 때 구분 컬럼에 입력할 값을 지정한다. 기본값은 엔티티의 이름이다.
@PrimaryKeyJoinColumn
name 속성을 통해 자식 테이블의 기본 키 컬럼명을 지정한다. 기본값은 부모 테이블의 ID 컬럼명이다.
장점
-테이블이 정규화된다.
-외래 키 참조 무결성 제약 조건을 활용할 수 있다.
-저장 공간을 효율적으로 사용한다.
단점
-조회할 때 조인이 많이 사용되므로 잘못 이용하면 성능이 저하될 여지가 있다.
-조회 쿼리가 복잡하다.
-데이터를 등록할 때 INSERT SQL을 두 번 실행한다.
2. 단일 테이블
단일 테이블은 테이블 하나에 모든 데이터를 다 넣는다.
구분 컬럼을 통해 어떤 자식 데이터가 저장되었는지 구분하며 조회시 조인 하지 않는다.
*주의:자식 엔티티가 매핑한 칼럼은 모두 NULL
'
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item {
@Id
@GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
private String name;
private int price;
}
@Entity
@DiscriminatorValue("A")
public class Album extends Item {
private String artist;
}
@Entity
@DiscriminatorValue("M")
public class Movie extends Item {
private String director;
private String actor;
}
@Entity
@DiscriminatorValue("B")
@PrimaryKeyJoinColumn(name = "BOOK_ID")
public class Book extends Item {
private String author;
private String isbn;
}
장점
-조인이 필요 없으므로 일반적으로 조회 성능이 빠르다.
-조회 쿼리가 단순하다.
단점
-자식 엔티티가 매핑한 컬럼이 모두 null을 허용해야 한다.
-단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다. 그러므로 상 황에 따라서는 조회 성능이 오히려 느려질 수 있다.
3.구현 클래스마다 테이블 생성
자식 엔티티마다 테이블을 만들고 각각 필요한 컬럼을 모두 만든다.
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Item {
@Id
@GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
private String name;
private int price;
}
@Entity
public class Album extends Item {
private String artist;
}
public class Movie extends Item {
private String director;
private String actor;
}
@Entity
public class Book extends Item {
private String author;
private String isbn;
}
구분 컬럼을 사용하지 않으며 일반적으로 잘 사용안한다.
장점
-서브 타입을 구분해서 처리할 때 효과적이다.
-not null 제약 조건을 사용할 수 있다.
단점
-여러 자식 테이블을 함께 조회할 때 성능이 느리다.
-SQL에 UNION을 사용해야 한다.
-위 예제 코드에서 em.find(Item.class) 같은 것을 호출하는 순간 자식 테이블을 전부 다 조회해야 한다.
-자식 테이블을 통합해서 쿼리하기 어렵다.
@MappedSuperclass
부모 클래스는 테이블과 매핑하지 않고 부모 클래스를 상속 받는 자식 클래스에게 매핑 정보만 제공하고 싶으면 해당 어노테이션을 사용한다. @MappedSuperclass는 추상 클래스와 비슷한데, @Entity는 실제 테이블과 매핑되지만 @MappedSuperclass는 실제 테이블과 매핑되지는 않는다. 단순히 매핑 정보를 위로 뽑아서 재사용할 목적으로 사용한다.
@MappedSuperclass
public abstract class BaseEntity {
@Id
@GeneratedValue
private Long id;
private String name;
}
@Entity
public class Member extends BaseEntity {
// ID 상속
// NAME 상속
private String email;
}
@Entity
public class Seller extends BaseEntity {
// ID 상속
// NAME 상속
private String shopName;
}
@MappedSuperclass의 특징
테이블과 매핑되지 않고 자식 클레스에 엔티티의 매핑 정보를 상속하기 위해 사용한다.
해당 어노테이션이 붙은 클래스는 엔티티가 아니다.
추상 클래스로 만드는 것을 권장한다.
Author And Source
이 문제에 관하여([DB] 테이블을 설계하자! -3), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@tjdud3550/DB-테이블을-설계하자-3저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)