Spring/JPA

[JPA] BaseEntity๋กœ ๊ณตํ†ต ์—”ํ‹ฐํ‹ฐ ์†์„ฑ ์ถ”์ƒํ™”ํ•˜๊ธฐ

27200 2025. 11. 6. 16:25

๐Ÿค” ์‹œ๊ฐ„๊ณผ ๊ฐ™์€ ๊ณตํ†ต ์—”ํ‹ฐํ‹ฐ ์†์„ฑ์„ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์—†์„๊นŒ?

์—”ํ‹ฐํ‹ฐ๋ฅผ ์ž‘์„ฑํ•˜๋‹ค ๋ณด๋ฉด ์ค‘๋ณต๋˜๋Š” ์ฝ”๋“œ๊ฐ€ ์ž์ฃผ ๋“ฑ์žฅํ•œ๋‹ค.
๋Œ€ํ‘œ์ ์ธ ์˜ˆ๋กœ ๋“ฑ๋ก๋œ ์‹œ๊ฐ„(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