JPA ์์๊ด๊ณ ๋งคํ ์ ๋ต
2022-10-28
JPA Entity ์์ ๊ด๊ณ ๋งคํ ์ ๋ต
๐ ์ถ์ฒ : ๊ฐ๋ฐ์์ ๊ธฐ๋ก์ต๊ด - [JPA] ์์๊ด๊ณ ๋งคํ ์ ๋ต(@Inheritance, @DiscriminatorColumn)
๊ณต๋ถํ๊ฒ ๋ ๋ฐฐ๊ฒฝ
- Spring ํ๋ก์ ํธ์
JPA Entity์ ์์ฑ, ์์ ์๊ฐ ๊ด๋ฆฌ๋ฅผ ์ํ ์นผ๋ผ์ด ์กด์ฌ.- ๊ตญ์ ํ๋ฅผ ์ํด
UTC๋ฅผ ๊ธฐ์ค์ผ๋ก ์ผ์ BE์์ ์ฒ๋ฆฌํ๊ณ ํด๋ผ์ด์ธํธ์์ ์๊ฐ์ ์์ฒญ ์ FE์์ ์ง์ญํํ๊ธฐ ์ํด@PrePersist,@PreUpdate์ด๋ ธํ ์ด์ ์ด ์ ์ฉ๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉ.- ํ๋ก์ ํธ์์ ๊ด๋ฆฌํ๋ Entity๊ฐ ํ๋๋ ๊ฒฝ์ฐ์๋ ๊ธฐ์ค ์๊ฐ์ UTC๋ก ์ผ์ ํ๊ฒ ๊ฐ์ ธ๊ฐ๊ธฐ ์ํด์ ์ ๋ฉ์๋๋ฅผ ์์๋ฐ๋๋ก BaseEntity๋ฅผ ์ค๊ณ
- ๊ทธ๋ฅ ์์ํ๋๊น
@Table์ด๋ ธํ ์ด์ ์ ์ค์ ํ ํ ์ด๋ธ์ด ์๋๋ผbaseEntity๋ผ๋ ์ด๋ฆ์ ํ ์ด๋ธ์ด ์๋ก ์๊ธฐ๋ฉด์DTYPE์ด๋ผ๋ ์นผ๋ผ์ ์๋ ํ ์ด๋ธ entity๋ช ์ด ์ ๋ ฅ ๋จ
DB์ super type :arrow_right: sub type๋ฅผ ๋ฌผ๋ฆฌ ๋ชจ๋ธ๋ก ๊ตฌํํ๋ 3๊ฐ์ง ๋ฐฉ๋ฒ
- Enttiy Diagram

- Entity.class
1@Entity 2public class BaseEntity { 3 @Id 4 @Column(name = "tuple_id") 5 private String tupleId; 6 @Column(name = "create_time") 7 private Timestamp createTime; 8 @Column(name = "update_time") 9 private Timestamp updateTime; 10 11 @PrePersist 12 public void beforeAdd() { 13 LocalDateTime ldt = LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC); 14 this.createTime = Timestamp.valueOf(ldt); 15 } 16 17 @PreUpdate 18 public void beforeUpdate() { 19 LocalDateTime ldt = LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC); 20 this.updateTime = Timestamp.valueOf(ldt); 21 } 22}
JOINED: ๊ฐ๊ฐ์ ํ ์ด๋ธ๋ก ์์ฑํ ๋ค ์กฐ์ธํ๋ ์ ๋ต
- implement code
1@Entity 2@Inheritance(strategy = InheritanceType.JOINED) 3@DiscriminatorColumn(name="DTYPE") //default๊ฐ DTYPE 4public class BaseEntity { 5 @Id 6 @Column(name = "tuple_id") 7 private String tupleId; 8 @Column(name = "create_time") 9 private Timestamp createTime; 10 @Column(name = "update_time") 11 private Timestamp updateTime; 12 13 @PrePersist 14 .. 15} base_item,app_a,app_b,app_c4๊ฐ์ ํ ์ด๋ธ์ด ๊ด๋ฆฌ๋๋ฉฐ base_item ํ ์ด๋ธ์๋ง tuple_id, create_time, update_time ์ ๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋๋ค. tuple_id ์นผ๋ผ์ด PK์ด์ FK๊ฐ ๋๋ค.- ํ์๋ก ์ ์ธํด์ผ ํ๋
@DiscriminatorColumn์ผ๋ก ์์ฑ๋DTYPE์นผ๋ผ์sub typeํ ์ด๋ธ ์ค ์ด๋ค ๊ณณ์ ๋ฐ์ดํฐ๊ฐ ์์ฑ๋์๋์ง ๋ช ์ํ๋ ์ญํ ์ด๋ฉฐ, default๋ ์ํฐํฐ ํด๋์ค ์ด๋ฆ์ด ์ฌ์ฉ๋๋ค (appA,appB,appC) app_aํ ์ด๋ธ์ ์ ๊ท ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ฉด insert query๊ฐ ๋ ๋ฒ ์คํ๋๋ฉฐ,app_a๋ฐ์ดํฐ๋ฅผ ์์ฑ ์๊ฐ๊ณผ ํจ๊ป ์กฐํํ๊ณ ์ ํ๋ฉด ์กฐ์ธ์ด ํ์ํด์ง๋ค.- DB ๊ด์ ์์ ๊ฐ์ฅ ์ ๊ทํ๋ ๊ตฌ์กฐ์ด๋ฉฐ ๋ฉ๋ชจ๋ฆฌ ์ธก๋ฉด์์๋ ์์ ์ด ์๋ค๊ณ ํ๋ค.
SINGLE_TABLE: ํตํฉ ํ ์ด๋ธ๋ก ๋ณํํ๋ ๋จ์ผ ํ ์ด๋ธ ์ ๋ต
- implement code
1@Entity 2@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 3//@DiscriminatorColumn default DTYPE์ผ๋ก ์นผ๋ผ ์์ฑํด์ค 4public class BaseEntity { 5 @Id 6 @Column(name = "tuple_id") 7 private String tupleId; 8 @Column(name = "create_time") 9 private Timestamp createTime; 10 @Column(name = "update_time") 11 private Timestamp updateTime; 12 13 @PrePersist 14 ... 15} - ๊ท๋ชจ๋ ๋ณต์ก๋๊ฐ ํฌ์ง ์์ ์ํฐํฐ๋ค์ ๊ฒฝ์ฐ ๋ชจ๋ ์ํฐํฐ์ ์นผ๋ผ์ ํ ํ
์ด๋ธ์ ๋ค ์ ์ฅํ๊ณ
DTYPE์ผ๋ก ๊ตฌ๋ถํ ์ ์๋ค. - insert query๋ ํ ๋ฒ์ด๊ณ , ์กฐ์ธ๋ ํ์๊ฐ ์๋ค.
- ์งํ ์ค์ธ ํ๋ก์ ํธ์์๋ appA~appC ์ ๋ํ ์นผ๋ผ ๋ณ๊ฒฝ์ด ๋น๋ฒํ๊ฒ ์ผ์ด๋๋ฉฐ DB๋ฅผ ์น์์๋ง ์ ๊ทผํ๋ ๊ตฌ์กฐ๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ํ ํ
์ด๋ธ์ ๋ชฐ์๋๊ณ
DTYPE์ผ๋ก ๊ตฌ๋ถํ์ฌ ์ฌ์ฉํ๊ธฐ์๋ ๋ฌด๋ฆฌ๊ฐ ์๋ค.
TABLE_PER_CLASS: ๊ตฌํ ํด๋์ค๋ง๋ค ํ ์ด๋ธ์ ์์ฑํ๋ ์ ๋ต
- implement code
1@Entity 2@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 3public class BaseEntity { 4 @Id 5 @Column(name = "tuple_id") 6 private String tupleId; 7 @Column(name = "create_time") 8 private Timestamp createTime; 9 @Column(name = "update_time") 10 private Timestamp updateTime; 11 12 @PrePersist 13 ... 14} - 1๋ฒ JOINED ์ ๋ต๊ณผ ์ ์ฌํด๋ณด์ด์ง๋ง
super type์ํฐํฐ์ ์นผ๋ผ๋ค์sub type์ ์ํฐํฐ ๋ชจ๋์ ๋์ผํ๊ฒ ์์ฑํ์ฌapp_a,app_b,app_c์ด 3๊ฐ์ ํ ์ด๋ธ์ ๊ด๋ฆฌํ๊ฒ ๋๋ค. super type์ํฐํฐ๋ก ์ ๊ทผํ ๊ฒฝ์ฐapp_a~app_c๋ฅผUNION์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ฌ ์กฐํํ๊ธฐ ๋๋ฌธ์ ์ด๋ฐ ๊ฒฝ์ฐ ์ฑ๋ฅ์ด ์ข๋ค๊ณ ํ ์๋ ์๋ค.
์ด๋ ธํ ์ด์ ๋ฑ ์ค์ ๊ฐ ์ ๋ฆฌ
๐ ์ถ์ฒ : victolee - [Spring JPA] ์์(JOINED ์ ๋ต์ ์ค์ฌ์ผ๋ก)
์์ ๊ด๊ณ ๊ด๋ จ
- @Inheritance
- ์ด๋ค ์์ ์ ๋ต์ ์ฌ์ฉํ ๊ฒ์ธ์ง ๋ช ์
- @DiscriminatorColumn
super type์ํฐํฐ์์ ์ด๋ค ์นผ๋ผ์ ์ฌ์ฉํ์ฌsub type์ํฐํฐ๋ฅผ ๊ตฌ๋ถํ ๊ฒ์ธ์ง ๋ช ์
- @DiscriminatorValue
- ์์ ์นผ๋ผ์์
sub type์ํฐํฐ ๋ณ๋ก ๊ฐ์ ๊ฐ์ง๋๋ก ์ง์ - DB์์ table column value๋ก ๋ค์ด๊ฐ ๊ฐ์ด๊ธฐ ๋๋ฌธ์ ์์ด/ํ๊ธ ๊ตฌ๋ถ ์์ด ์ฌ์ฉ ๊ฐ๋ฅ
- ์์ ์นผ๋ผ์์
๊ฐ์ฒด ๋งคํ ๊ด๋ จ
- @MappedSuperclass
- ๊ฐ์ฒด ์งํฅ์ ์ผ๋ก๋ ์์ ๊ด๊ณ๋ฅผ ์ ์งํ์ง๋ง ์ค์ ๊ตฌํ๋ entity์๋ ์ํฅ์ ์ฃผ์ง ์๊ธฐ ์ํด์ ์ฌ์ฉ
super type์ํฐํฐ์์@Entity๋์@MappedSuperclass๋ก ์ ์ธ- ์ค์ ๋ก ๊ตฌํ ๋ ์ํฐํฐ๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ์ถ์ํด๋์ค๋ก ์ ์ธ
@ID๋ก ์ ์ธํด์ ์ฌ์ฉํ id ์นผ๋ผ๋ ํ์์์
- ์์ ์์ ์์
BaseEntity์ ์ด ์ด๋ ธํ ์ด์ ์ ์ ์ฉํ๋ฉดBaseEntity์ ๋ํ ์ํฐํฐ๋ ์์ฑ๋์ง ์๊ณ ,TABLE_PER_CLASS์ ๋ต์ ์ ์ฉํ ๊ฒ๊ณผ ์ ์ฌํ๊ฒBaseEntity์ ์๋ ์นผ๋ผ์ ๋ชจ๋ ์์sub type์ํฐํฐ์ ํฌํจํ์ฌ ์์ฑ
- @AttributeOverride / @AttributeOverrides
@MappedSuperclass๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ๋ถ๋ชจ ํด๋์ค์ ํน์ ์นผ๋ผ์ overrideํ๋ ค๊ณ ํ ๋ ์ฌ์ฉ
1@MappedSuperclass 2public abstract class BaseEntity{ 3 @Column(name = "create_time") 4 private Timestamp createTime; 5 @Column(name = "update_time") 6 private Timestamp updateTime; 7} 8 9@Entity 10@AttributeOverride(name="updateTime", column=@Column(name="app_a_update_time")) 11public class AppA extends BaseEntity{ 12 private String appAVar; 13} 14 15@Entity 16@AttributeOverrides({ 17 @AttributeOverride(name="createTime", column=@Column(name="app_b_create_time")), 18 @AttributeOverride(name="updateTime", column=@Column(name="app_b_update_time")), 19}) 20public class AppB extends BaseEntity{ 21 private String appBVar; 22}
๊ฒฐ๋ก
- ์๋ ์ ์ฉํ๋ ค๊ณ ํ๋ ๋ด์ฉ์
@MappedSuperclass๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ฉํ์์ - ๊ธฐ์กด์ QueryDsl๋ก ์ง์ ์กฐ์ธํ์ฌ select ํ๋๋ก ์ค๊ณํ๋ ๋ถ๋ถ์ JAVA code ์์์ ๋ช ์์ ์ผ๋ก ์์ ๊ด๊ณ์ ์์์ ํ์ ํ ์ ์๋๋ก ๊ด๋ จ์๋ ์ํฐํฐ๋ค์ JOINED ์ ๋ต์ ์ ์ฉํ์์
์ฐธ์กฐ
- Entity์์๋ ์ฌ๋ฌ ๋ณ์์ @Id๋ฅผ ์ ์ธํ์ฌ ๋ณตํฉํค๋ก์จ ์ฌ์ฉํ ์ ์๋๋ฐ, ์ด ๊ฒฝ์ฐ @GeneratedValue๋ฅผ ์ฌ์ฉํ ์๊ฐ ์๋ค. ์ง์ ํ ๋น๋ง ๊ฐ๋ฅ
(์ถ์ฒ : catpark's something new - jpa ๋ณตํฉํค์์ auto increment)
/end of JPA ์์๊ด๊ณ ๋งคํ ์ ๋ต
CONTENT LISTMERRI๏ผs DEVELOG
2022-11-09
2022-10-20