다음과 같은 논리적 상속관계를 DB상에 물리적으로 어떻게 나타내야하는지 고민했다.
조인테이블 전략을 사용하였다.
(장단점은 맨 아래에 요약)
참고)
Join Table 전략 : 여러 테이블 사용
- 관리해야 할 테이블이 많아짐
- 객체지향스럽지 않고 복잡함
=> Single Table 전략을 현업에서 좀 더 많이 사용하기도 함
Join 전략으로 매핑하면 다음과 같이 superclass와 subclass의 table이 구성된다.
Springboot를 통해 상속관계 DB매핑 적용하기
super class
▶ 참고:
@DiscriminatorColumn 지정은 상속관계매핑의 JoinTable 전략에서 필수가 아니다. (본인도 필요가 없어져서 나중에 없앰)
참고로, 하나의 테이블로 상속관계가 매핑되는 Single Table 전략에서는 지정해야 한다. (하나의 테이블이니까 타입을 구분해주는 컬럼이 필요하기 때문)
@Entity
@Inheritance(strategy= InheritanceType.JOINED) //상속관계 매핑전략 지정
@DiscriminatorColumn(name="DTYPE") //자식클래스 구별을 위한 column 이름을 DTYPE으로 지정. 자식클래스에서 @DiscriminatorValue("값") 의 값을 통해 자식들끼리 구별된다 (default : 클래스명)
@NoArgsConstructor
public abstract class Marker implements Markable { //@Inheritance를 사용하기 위해서는 abstract class여야함
@Id @GeneratedValue
private int id;
@Column
private int x;
@Column
private int y;
public Marker(Point point){
this.x = point.getX();
this.y = point.getY();
}
public Point getPoint(){
return new Point(this.x, this.y);
}
}
@Getter
@AllArgsConstructor
class Point {
private int x;
private int y;
}
sub class 3개
@Entity
@DiscriminatorValue("Loss")
@NoArgsConstructor
public class LossMarker extends Marker{
// sub table 에서 Id => super table 에서 data 가 가지는 Id
@Column
private Date date;
@Column
private String contents;
public LossMarker(Point point, Date date, String contents) {
super(point);
this.date = date;
this.contents = contents;
}
}
@Entity
@DiscriminatorValue("Pic")
@NoArgsConstructor
public class PicMarker extends Marker{
// sub table 에서 Id => super table 에서 data 가 가지는 Id
@Column
private BlobJavaType pic;
@Column
private String contents;
public PicMarker(Point point, BlobJavaType pic, String contents) {
super(point);
this.pic = pic;
this.contents = contents;
}
}
@Entity
@DiscriminatorValue("Talk")
@NoArgsConstructor
public class TalkMarker extends Marker{
// sub table 에서 Id => super table 에서 data 가 가지는 Id
@Column
private String contents;
public TalkMarker(Point point, String contents) {
super(point);
this.contents = contents;
}
}
매핑시 로그 확인해보기
: EntityBinder가 동작함
: @DiscrimiatorColumn을 사용했기 때문에 뜨는 WARN을 발견
WARN 16064 --- [ main] o.h.cfg.annotations.EntityBinder :
HHH000457: Joined inheritance hierarchy [com.example.demo.entity.Marker]
defined explicit @DiscriminatorColumn.
Legacy Hibernate behavior was to ignore the @DiscriminatorColumn.
However, as part of issue HHH-6911 we now apply the explicit @DiscriminatorColumn.
If you would prefer the legacy behavior,
enable the `hibernate.discriminator.ignore_explicit_for_joined` setting (hibernate.discriminator.ignore_explicit_for_joined=true)
테이블 생성 sql 확인해보기
step1. 일단 table을 생성하더라
이때 marker_seq라는 table은 내가 만들지 않았는데 생성되었다.
Hibernate:
create table loss_marker (
contents varchar(255),
date date,
id integer not null,
primary key (id)
) engine=InnoDB
Hibernate:
create table marker (
dtype varchar(31) not null,
id integer not null,
x integer,
y integer,
primary key (id)
) engine=InnoDB
Hibernate:
create table marker_seq (
next_val bigint
) engine=InnoDB
Hibernate:
insert into marker_seq values ( 1 )
Hibernate:
create table pic_marker (
contents varchar(255),
pic varbinary(255),
id integer not null,
primary key (id)
) engine=InnoDB
Hibernate:
create table talk_marker (
contents varchar(255),
id integer not null,
primary key (id)
) engine=InnoDB
step2. super table과 sub table간 관계를 설정하는 부분 발견
각 subclass에 FK 참조 제약조건을 부여하고 있다.
이때 subclass마다 부여하는 FK 참조값은 모두 다른 것 또한 확인했다.
=> 왜 그래야 할까?
Hibernate:
alter table loss_marker
add constraint FK6tlu1nh8ck27i0jqjrr8b9po5
foreign key (id)
references marker (id)
Hibernate:
alter table pic_marker
add constraint FKb4wu72kh4qtquyi3c3wb85085
foreign key (id)
references marker (id)
Hibernate:
alter table talk_marker
add constraint FK78hjd3wgn1k75r00x424sb5yw
foreign key (id)
references marker (id)
매핑된 테이블 결과
: sub class data의 id <= super class data의 id
: super class의 dtype column을 통해 subclass가 구분된다.
super class
marker
sub class 3개
pic_marker
talk_marker
loss_marker
요약하기
논리적 상속관계를 물리적으로 매핑 (DB에반영)하기 위하여 Join 전략을 선택했다.
선택 이유는 table이 보기에 깔끔하게 구성되는 것 같았기 때문이다.
상속관계 DB 매핑시 이러한 Join 전략을 사용할 때의 장단점은 다음과 같다.
장점
- 테이블 정규화, 저장공간 효율, FK 참조 활용
단점
- 조회할 때 : join을 많이 사용하여 성능저하 & 복잡한 조회 쿼리
- 저장할 때 : insert문이 2번 호출됨
전적으로 이 링크를 참고하였다.
https://rlawls1991.tistory.com/entry/%EC%83%81%EC%86%8D%EA%B4%80%EA%B3%84-%EB%A7%A4%ED%95%91
고급 매핑 - 상속관계 매핑
상속관계 매핑 1. 정리 1) 관계형 데이터베이스는 상속 관계X 2) 슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사 3) 상속관계 매핑 상속관계 매핑이란? 객체의 상속과 구조와 DB의 슈
rlawls1991.tistory.com
'Database' 카테고리의 다른 글
[DB] 인덱스 사용 이유 이해하기 (0) | 2023.10.17 |
---|---|
[H2] Column이 drop 되지 않음 | JPA Bean을 직접 주입하는 실습 중 (0) | 2023.01.25 |
mysql 서버 상태 확인하기(show status) | db connection 전후 Threads 관련 상태변수 확인 (0) | 2023.01.11 |
ObjectInputStream | file에 이어쓰기로 writeObject 후 readObject하려할 때 object를 못읽는 문제 (0) | 2022.12.28 |
FK 제약조건 삭제하기 - Cannot drop column <FK컬럼명>: needed in a foreign key constraint (1) | 2022.10.11 |