왜
spring 에서 전파단계를 학습하여, Transaction을 더 잘 다뤄보자
테스트 상황
둘다 @Transactional을 의존하며,
PaymentService.processPayment() -> PointService.usePoint()를 호출한다.
1 | graph LR |
테스트 방법
usePoint() 메서드의 @Transactional(propagation = XXX) 전파 단계를 바꿔가며,
상황 및 에러를 확인해보자
전파 단계별 특징과 예시
REQUIRED
의미: 트랜잭션이 필요함(없으면 새로 만듬)
- 기존 트랜잭션 없음: 새로운 트랜잭션을 생성함
- 기존 트랜잭션이 있음: 기존 트랜잭션에 참여함
예시
각 메서드의
@Transactional설정processPayment()
@Transactional- Try-catch 문으로 usePoint()의 예외 처리됨
usePoint()
@Transactionalthrow IllegalArgumentException("Treansactional 테스트용 예외")
이 전파단계에서의 에러
1
org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only
REQUIRES_NEW
- 의미: 항상 새로운 트랜잭션이 필요함
- 기존 트랜잭션 없음: 새로운 트랜잭션을 생성함
- 기존 트랜잭션이 있음: 기존 트랜잭션을 보류시키고 새로운 트랜잭션을 생성함
- 예시
- 각 메서드의
@Transactional설정- processPayment()
@Transactional- Try-catch 문으로 usePoint() 예외 처리완료.
- usePoint()
@Transactional(propagation = Propagation.REQUIRES_NEW)throw IllegalArgumentException("Treansactional 테스트용 예외")
- processPayment()
- 이 전파단계에서의 에러
- 없음. -> rollback-only 마크가 상위 트랜잭션에게 전달되지않는다.
- 각 메서드의
SUPPORTS
의미: 트랜잭션이 있으면 지원함(트랜잭션이 없어도 됨)
- 기존 트랜잭션 없음: 트랜잭션 없이 진행함
- 기존 트랜잭션이 있음: 기존 트랜잭션에 참여함
예시
각 메서드의
@Transactional설정- processPayment()
@Transactional- Try-catch 문으로 usePoint() 예외 처리완료.
- usePoint()
@Transactional(propagation = Propagation.SUPPORTS)throw IllegalArgumentException("Treansactional 테스트용 예외")
- processPayment()
이 전파단계에서의 에러 -> 기존 트랜잭션 존재했으므로 rollback-only marked
1
org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only
NOT_SUPPORTED
의미: 트랜잭션을 지원하지 않음(트랜잭션 없이 진행함)
- 기존 트랜잭션 없음: 트랜잭션 없이 진행함
- 기존 트랜잭션이 있음: 기존 트랜잭션을 보류시키고 트랜잭션 없이 진행함
예시
각 메서드의
@Transactional설정processPayment()
@Transactional
usePoint()
@Transactional(propagation = Propagation.NOT_SUPPORTED)- SQL 쿼리문 실행
이 레벨에서의 에러 : Transaction 이 없어서 쿼리 실행불가
1
jakarta.persistence.TransactionRequiredException: Query requires transaction be in progress, but no transaction is known to be in progress
MANDATORY
의미: 트랜잭션이 의무임(트랜잭션이 반드시 필요함)
- 기존 트랜잭션 없음: IllegalTransactionStateException 예외 발생
- 기존 트랜잭션이 있음: 기존 트랜잭션에 참여함
예시
각 메서드의
@Transactional설정- processPayment()
- X
- usePoint()
@Transactional(propagation = Propagation.MANDATORY)- SQL 쿼리문 실행
- processPayment()
이 전파단계에서의 에러 :
1
org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
NEVER
의미: 트랜잭션을 사용하지 않음(기존 트랜잭션도 허용하지 않음)
- 기존 트랜잭션 없음: 트랜잭션 없이 진행
- 기존 트랜잭션이 있음:
IllegalTransactionStateException예외 발생
예시
- 각 메서드의
@Transactional설정- processPayment()
@Transactional
- usePoint()
@Transactional(propagation = Propagation.NEVER)- SQL 쿼리문 실행
- processPayment()
- 이 전파단계에서의 에러 :
1
org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'
- 각 메서드의