안녕세계
[Spring] @PostPersist와 TransactionPhase.AFTER_COMMIT 본문
[Spring] @PostPersist와 TransactionPhase.AFTER_COMMIT
Junhong Kim 2024. 6. 30. 23:34@PostPersist와 @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)는 모두 Spring에서 트랜잭션 관련 이벤트를 처리하는데 사용됩니다. 두 어노테이션은 동작 시점과 사용 용도가 다르므로 차이를 이해하고 사용해야합니다. 본 포스팅에서는 두 어노테이션의 차이점에 대해 알아봅니다.
@PostPersist
- 동작 시점
- 엔티티가 영속성 컨텍스트에 저장된 직후 호출됩니다. 즉, persist 메서드가 호출된 후를 의미합니다.
- 데이터베이스에 INSERT 연산이 수행된 후 호출되며, 트랜잭션 commit이 되기 전에 호출됩니다.
fun main() {
val emf: EntityManagerFactory = Persistence.createEntityManagerFactory("hello")
val em: EntityManager = emf.createEntityManager()
val myEntity = MyEntity(name = "kim")
em.transaction.begin()
em.persist(myEntity)
println("=========before commit======")
em.transaction.commit()
println("=========after commit======")
em.close()
emf.close()
}
---
@PrePersist entity: kim
Hibernate:
/* insert for
hellojpa.MyEntity */insert
into
MyEntity (name, id)
values
(?, default)
@PostPersist entity: kim
=========before commit======
=========after commit======
- 사용 방법
- JPA 엔티티 클래스에 직접 정의합니다.
- @EntityListeners를 사용하여 JPA 엔티티 생명 주기 이벤트를 처리할 수 있습니다.
- 엔티티 리스너는 엔티티의 상태 변화에 따라 특정 콜백 메서드를 호출하여 다양한 작업을 할 수 있습니다..
- 용도
- 엔티티가 영속성 컨텍스트에 추가된 후 후속 작업을 수행하기 위해 사용됩니다.
JPA entity 클래스에 직접 정의
@Entity
class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long? = null,
val name: String
@PrePersist
fun prePersist() {
println("@PrePersist entity: " + this);
}
@PostPersist
fun postPersist() {
println("@PostPersist entity: " + this);
}
}
@EntityListeners 사용
@EntityListeners(MyEntityListener.class)
@Entity
class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long? = null,
val name: String
}
class MyEntityListener {
@PrePersist
fun prePersist(entity: MyEntity) {
println("@PrePersist entity: " + entity.name);
}
@PostPersist
fun postPersist(entity: MyEntity) {
println("@PostPersist entity: " + entity.name);
}
}
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
- 동작 시점
- 트랜잭션이 commit 된 후 호출됩니다.
- 사용 위치
- Spring Bean 클래스에 사용합니다.
- @TransactionalEventListener를 사용하려면 해당 클래스가 Spring 빈으로 등록되어야 합니다.
- Spring Bean 클래스에 사용합니다.
- 용도
- 트랜잭션 commit이 완료된 후 이벤트를 수신하여 작업을 처리하기 위해 사용됩니다.
data class MyEvent(val entityId: Long)
@Entity
data class MyEntity(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long? = null,
val name: String
)
@Service
class MyService(
@Autowired private val entityManager: EntityManager,
@Autowired private val eventPublisher: ApplicationEventPublisher
) {
@Transactional
fun saveEntity(name: String) {
val entity = MyEntity(name = name)
entityManager.persist(entity)
// 트랜잭션 내에서 이벤트 발행
eventPublisher.publishEvent(MyEvent(entity.id!!))
}
}
@Component
class MyEventListener {
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
fun handleAfterCommit(event: MyEvent) {
// 트랜잭션이 커밋된 후에 실행되는 로직
println("Transaction has been committed. Entity ID: ${event.entityId}")
}
}
Q1) @PostPersist가 호출되는 시점을 commit 후로 변경할 수 있을까?
@PostPersist는 JPA entity의 라이프사이클 콜백 메서드로, 엔티티가 영속성 컨텍스트에 추가된 후에 호출되기 때문에 트랜잭션 commit 후로 변경할 수 없습니다. 트랜잭션 commit 후에 작업을 처리하기 위해서는 @TransactionEventListener를 사용해야합니다.
Q2) @TransactionEventListener를 사용하여 commit 전에 이벤트를 처리할 수 있을까?
@TransactionalEventListener는 phase 속성을 사용하여 트랜잭션 이벤트를 처리할 시점을 지정할 수 있습니다. commit 전에 이벤트를 처리하려면 BEFORE_COMMIT 옵션을 사용하면 됩니다. 더 자세한 내용은 [Spring] EventListener vs TransactionalEventListener 포스팅에서 확인하실 수 있습니다.
'Server > Spring' 카테고리의 다른 글
[Spring] SSE란? (feat. SseEmitter) (0) | 2024.03.03 |
---|---|
[Spring] JPA 성능 최적화 (0) | 2023.05.06 |
[Spring] 그라파나와 로키로 애플리케이션 로그 조회하기 (0) | 2023.04.22 |
[Spring] 그라파나와 프로메테우스로 애플리케이션 모니터링하기 (0) | 2023.04.09 |
[Spring] EventListener vs TransactionalEventListener (0) | 2023.03.08 |