๐ค ์๊ฐ๊ณผ ๊ฐ์ ๊ณตํต ์ํฐํฐ ์์ฑ์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์์๊น?
์ํฐํฐ๋ฅผ ์์ฑํ๋ค ๋ณด๋ฉด ์ค๋ณต๋๋ ์ฝ๋๊ฐ ์์ฃผ ๋ฑ์ฅํ๋ค.
๋ํ์ ์ธ ์๋ก ๋ฑ๋ก๋ ์๊ฐ(createdAt), ์์ ๋ ์๊ฐ(updatedAt) ๊ณผ ๊ฐ์ ํ๋๊ฐ ์๋ค.
์ด ํ๋๋ ๊ฑฐ์ ๋ชจ๋ ์ํฐํฐ์ ํ์ํ์ง๋ง,
๋งค๋ฒ ๊ฐ์ ์ฝ๋๋ฅผ ๋ฐ๋ณตํด์ ์์ฑํ๋ ๊ฒ์ ๋ถํ์ํ๊ณ ์ ์ง๋ณด์์๋ ์ข์ง ์๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด ์๊ฐ ๊ด๋ จ ์์ฑ์ ํจ์จ์ ์ผ๋ก ์ถ์ํํ ์๋ ์์๊น?
๊ทธ๋ฆฌ๊ณ ํ ๋ฒ ๋ง๋ค์ด๋๋ฉด ์๋์ผ๋ก ๊ด๋ฆฌ๋๊ฒ ํ ์ ์์๊น?
๐ก ์ถ์ ํด๋์ค BaseEntity๋ก ๊ณตํต ํ๋ ์ถ์ํํ๊ธฐ
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ๊ณตํต ์์ฑ์ ๊ด๋ฆฌํ๋ ์ถ์ ํด๋์ค(BaseEntity)๋ฅผ ๋๋ ๊ฒ์ด๋ค.
JPA์ @MappedSuperclass์ ์คํ๋ง ๋ฐ์ดํฐ JPA์ Auditing ๊ธฐ๋ฅ์ ํจ๊ป ์ฌ์ฉํ๋ฉด,
์์ฑ ์๊ฐ๊ณผ ์์ ์๊ฐ์ ์๋์ผ๋ก ๊ด๋ฆฌํ ์ ์๋ค.
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@Slf4j
public abstract class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
@PrePersist
public void beforeInsert() {
log.info("[PrePersist] ์ ์ฅ ์ง์ ! createdAt={}, updatedAt={}", createdAt, updatedAt);
}
@PreUpdate
public void beforeUpdate() {
log.info("[PreUpdate] ์์ ์ง์ ! updatedAt={}", updatedAt);
}
}
@Entity
public class Member extends BaseEntity {
@Id
private String name;
private String address;
private String phone;
// ์์ฑ์
public Member(String name, String address, String phone) {
this.name = name;
this.address = address;
this.phone = phone;
}
public Member() {}
void updatePhoneNumber(String phoneNumber) {
this.phone = phoneNumber;
}
}
๐น @MappedSuperclass
- ํด๋น ํด๋์ค๋ ํ ์ด๋ธ๋ก ์ง์ ๋งคํ๋์ง ์๋๋ค.
- ํ์ ์ํฐํฐ(Member, Order, Post ๋ฑ)๊ฐ ์์๋ฐ์ผ๋ฉด
createdAt, updatedAt ํ๋๊ฐ ๊ทธ ์ํฐํฐ์ ํ ์ด๋ธ ์ปฌ๋ผ์ผ๋ก ํฌํจ๋๋ค. - ์ฆ, DB์ BaseEntity ํ ์ด๋ธ์ ์์ฑ๋์ง ์๋๋ค.
๐น @EntityListeners(AuditingEntityListener.class)
- JPA์ ์ํฐํฐ ์ด๋ฒคํธ ๊ฐ์ง ๊ธฐ๋ฅ์ ํ์ฑํํ๋ค.
- ์คํ๋ง ๋ฐ์ดํฐ JPA์ AuditingEntityListener๊ฐ ์ํฐํฐ์ ์ ์ฅ/์์ ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํ์ฌ
@CreatedDate, @LastModifiedDate์ ์๋์ผ๋ก ๊ฐ์ ๋ฃ์ด์ค๋ค.
๐ ์ด ๊ธฐ๋ฅ์ด ๋์ํ๋ ค๋ฉด ํ๋ก์ ํธ ๋ด์ ๋ฐ๋์ ์๋ ์ค์ ์ด ํ์ํ๋ค.
@Configuration
@EnableJpaAuditing
public class JpaConfig {}
or
@SpringBootApplication
@EnableJpaAuditing
public class DemoApplication {
๐น @CreatedDate, @LastModifiedDate
- ์ํฐํฐ์ ์์ฑ์ผ๊ณผ ์์ ์ผ์ ์๋์ผ๋ก ๊ธฐ๋กํ๋ ์ด๋ ธํ ์ด์ .
- @CreatedDate → ์ํฐํฐ ์ต์ด ์ ์ฅ ์ ํ ๋ฒ๋ง ์๋ ์ ๋ ฅ
- @LastModifiedDate → ์ํฐํฐ๊ฐ ์์ ๋ ๋๋ง๋ค ์๋ ๊ฐฑ์
๐น @PrePersist, @PreUpdate
- JPA์ ์ํฐํฐ ์๋ช ์ฃผ๊ธฐ ์ฝ๋ฐฑ(Lifecycle Callback) ์ด๋ ธํ ์ด์ ์ด๋ค.
- ๊ฐ๊ฐ INSERT ์คํ ์ง์ , UPDATE ์คํ ์ง์ ์ ํธ์ถ๋๋ค.
- ์ด ์์ ์์๋ ๋จ์ํ ๋ก๊ทธ๋ฅผ ์ฐ์ง๋ง,
์ค์ ๋ก๋ ํน์ ๊ฐ ์ด๊ธฐํ๋ ์ปค์คํ ๋ก์ง์ ์ถ๊ฐํ ์๋ ์๋ค.
๐คฉ ์ค์ ์คํ ๋ก๊ทธ๋ก ๋ณด๋ ๋์ ๊ณผ์
1๏ธโฃ Hibernate: select ... from member where m1_0.name=?
2๏ธโฃ [PrePersist] ์ ์ฅ ์ง์ ! createdAt=2025-11-06T16:13:19.266154, updatedAt=2025-11-06T16:13:19.266154
3๏ธโฃ Hibernate: insert into member (address, created_at, phone, updated_at, name) values (?, ?, ?, ?, ?)
1๏ธโฃ Hibernate: select ... from member where m1_0.name=?
2๏ธโฃ [PreUpdate] ์์ ์ง์ ! updatedAt=2025-11-06T16:13:21.879723
3๏ธโฃ Hibernate: update member set address=?, phone=?, updated_at=? where name=?
์ค์ ์ฝ๋๋ฅผ ๋์์์ผ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
์ฆ, ๋งค๋ฒ ์ํฐํฐ๋ฅผ ๊ฑด๋๋ฆด ๋๋ง๋ค ์๊ฐ์ ๋ํ ์ค์ ์ ํด์ค์ผํ๋ ๊ฒ์ด ์๋ JPA๊ฐ ์๋์ผ๋ก ์ค์ ์ ํ๊ฒ ํด์ฃผ๋ ๊ฒ์ด๋ค.
๊ทธ ์ธ ๋ค์ํ ์์ ์ JPA๋ฅผ ์กฐ์ํด์ผํ ์ผ์ด ์๋ค๋ฉด ์๋ ๊ธ์ ์ฐธ๊ณ ํ์.
https://to-travel-coding.tistory.com/463
[JPA]JPA Entity ์๋ช ์ฃผ๊ธฐ(Entity LifeCycle)
1๏ธโฃ ์ํฐํฐ ์๋ช ์ฃผ๊ธฐ๋?JPA์์ ์ํฐํฐ(Entity) ๋ ๋จ์ํ ์๋ฐ ๊ฐ์ฒด(POJO)๊ฐ ์๋๋ค.EntityManager๊ฐ ๊ด๋ฆฌํ๋ “์์์ฑ ์ปจํ ์คํธ(Persistence Context)” ์์์ ์ํ๋ฅผ ๊ฐ์ง๋ ๊ฐ์ฒด๋ก ์กด์ฌํ๋ค.์ฆ, ์ํฐํฐ
to-travel-coding.tistory.com
'Spring > JPA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [JPA]JPA Entity ์๋ช ์ฃผ๊ธฐ(Entity LifeCycle) (0) | 2025.11.06 |
|---|