시그마 삽질==six 시그마

@TransactionalEventListener 본문

프로그래밍/Spring

@TransactionalEventListener

Ethan Matthew Hunt 2020. 10. 22. 01:34
An EventListener that is invoked according to a TransactionPhase.

If the event is not published within an active transaction, the event is discarded unless the fallbackExecution() flag is explicitly set. If a transaction is running, the event is processed according to its TransactionPhase.

Adding @Order to your annotated method allows you to prioritize that listener amongst other listeners running before or after transaction completion.
  • 트랜잭션 상태에 따른 이벤트 처리
  • 내가 원하는 트랜잭션 시점에 이벤트 발생하게 가능
  • @Async와 결합시 이벤트를 트랜잭션 커밋 이후에(성공 후에) 비동기로도 처리 가능.
  • 보통 A라는 트랜잭션 커밋 후에(성공 후에)  B라는 부수적 작업을 별도의 트랜잭션으로 해서 처리하고 싶을때 사용. B에서 에러가 발생해도 A까지 롤백x
  • 비지니스 로직에서는 예를 들면 회원가입후 가입축하 알림, 메일을 보내는경우.. 가입축하알림이나 메일이 예외발생했다고 성공적인 회원가입을 롤백하면 말이 안된다. 

간단한 예시지만

주문 성공 후 주문 완료 메일 발송시 메일 발송 실패로 주문까지 영향 미치게 하고 싶지 않을때...

@Service
@Transactional
@RequiredArgsConstructor
public class OrderService {
	private final OrderRepository orderRepository;
	private final ApplicationEventPublisher applicationEventPublisher;  //추가

	public void create(OrderCreateDto dto){
		Order order = orderRepository.save(dto.entity());
		applicationEventPublisher.publishEvent(new OrderNotificationEvent(order.getEmail()));//이벤트 등록
	}
}

 

 

@Component
@RequiredArgsConstructor
public class OrderNotificationEventListener {

	private final EmailSendService mailSendService;

    //@Async
	@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) //커밋완료 후 작업
	@Transactional(propagation = Propagation.REQUIRES_NEW)// 새로운 트랜잭션으로 구성
	public void notify(OrderNotificationEvent orderNotificationEvent){
		mailSendService.send(orderNotificationEvent.getEmail());
        throw new RuntimeException("error occur");// 메일전송시 에러 발생해도 주문은 롤백 안됨!!!!
	}
}

 

public enum TransactionPhase {

	/**
	 * Fire the event before transaction commit.
	 * @see TransactionSynchronization#beforeCommit(boolean)
	 */
	BEFORE_COMMIT,

	/**
	 * Fire the event after the commit has completed successfully.
	 * <p>Note: This is a specialization of {@link #AFTER_COMPLETION} and
	 * therefore executes in the same after-completion sequence of events,
	 * (and not in {@link TransactionSynchronization#afterCommit()}).
	 * @see TransactionSynchronization#afterCompletion(int)
	 * @see TransactionSynchronization#STATUS_COMMITTED
	 */
	AFTER_COMMIT,

	/**
	 * Fire the event if the transaction has rolled back.
	 * <p>Note: This is a specialization of {@link #AFTER_COMPLETION} and
	 * therefore executes in the same after-completion sequence of events.
	 * @see TransactionSynchronization#afterCompletion(int)
	 * @see TransactionSynchronization#STATUS_ROLLED_BACK
	 */
	AFTER_ROLLBACK,

	/**
	 * Fire the event after the transaction has completed.
	 * <p>For more fine-grained events, use {@link #AFTER_COMMIT} or
	 * {@link #AFTER_ROLLBACK} to intercept transaction commit
	 * or rollback, respectively.
	 * @see TransactionSynchronization#afterCompletion(int)
	 */
	AFTER_COMPLETION

}

 

참고

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/event/TransactionalEventListener.html

 

https://javacan.tistory.com/entry/Handle-DomainEvent-with-Spring-ApplicationEventPublisher-EventListener-TransactionalEventListener

 

 

'프로그래밍 > Spring' 카테고리의 다른 글

Spring webflux  (0) 2022.07.19
Spring batch 요약  (0) 2020.10.25
Spring Cloud Netflix  (0) 2020.10.18
Spring Kafka Basic  (0) 2020.08.25
ObjectMapper & OrikaMapper basic  (0) 2020.08.24
Comments