작성
·
2.2K
0
@Slf4j
@Service
public class MainService {
public void methodA() {
log.info("=== methodA 시작... ===");
// 비즈니스 로직 A ....
methodB();
log.info("=== methodA 종료... ===");
}
@Transactional
public void methodB() {
log.info("=== methodB 시작... ===");
log.info("-> is methodB transaction active? = {}", TransactionSynchronizationManager.isActualTransactionActive());
// 비즈니스 로직 B ....
log.info("=== methodB 종료... ===");
}
}
@Controller
@RequiredArgsConstructor
public class MainController {
private final MainService mainService;
public ResponseEntity<Void> transactionalTestMethod() {
mainService.methodA();
return ResponseEntity.ok().build();
}
}
이러한 MainService 구조에서 MainController에서 mainSerivce.methodA()를 호출하게 되면 methodA는 현재 트랜잭션을 유도하지 않고 있고 그 내부적으로 methodB는 내부 프록시 호출이기 때문에 당연히 methodB에는 트랜잭션 처리가 되지 않음은 이해하였습니다
그런데 이와 관련해서 실험을 하던 도중에
@Slf4j
@Service
public class MainService {
@Transactional
public void methodA() {
log.info("=== methodA 시작... ===");
// 비즈니스 로직 A ....
methodB();
log.info("=== methodA 종료... ===");
}
@Transactional
public void methodB() {
log.info("=== methodB 시작... ===");
log.info("-> is methodB transaction active? = {}", TransactionSynchronizationManager.isActualTransactionActive());
// 비즈니스 로직 B ....
log.info("=== methodB 종료... ===");
}
}
이러한 MainService 구조에서 mainService.methodA를 호출할 때 methodA에는 트랜잭션 처리가 됨이 당연한데 그 내부적으로 this.methodB를 호출하면 methodB에도 TransactionSynchronizationManager.isActualTransactionActive()의 결과가 true로 나옴에 따라 트랜잭션 처리가 되는 것 같습니다
제가 알고있던 것은 methodA에서 트랜잭션 처리가 진행이 되더라도 methodB는 내부적으로 호출되는 메소드이기 때문에 트랜잭션 처리가 이루어지지 않는다고 알고있었습니다
물론 Log를 찍어도 methodB 전 후에는 Participating transaction 관련 로그는 없었습니다
하지만 methodB에서 TransactionSynchronizationManager.isActualTransactionActive()의 결과가 true로 나옴에 따라 트랜잭션 처리가 유지되는 것 같은데 혹시 위와 같은 구조에서도 트랜잭션 처리가 유효한건가요?
답변 1
0
혹시 이 두가지 방식의 차이점?이라고 할 수 있는게 있을까요??
그냥 단순히 [내부적으로 포함하냐] or [REQUIRED에 의해서 기존 활성화 트랜잭션에 참여하냐] 이 느낌인가요?
methodA에서 methodB를 내부 호출하더라도 methodA 자체적으로 트랜잭션이 활성화 되어있기 때문에 methodB는 그대로 해당 트랜잭션을 사용하는거군요
this.methodB() -> 그냥 활성화된 트랜잭션에 참여 (별도의 로그 X)
별도의 mainNestedService.methodB() -> 기본 REQUIRED이므로 methodA에서 활성화된 트랜잭션에 참여 (별도의 로그 O -> participate)
이렇게 이해하면 되는거 맞죠??
-> 맞습니다.
혹시 이 두가지 방식의 차이점?이라고 할 수 있는게 있을까요??
그냥 단순히 [내부적으로 포함하냐] or [REQUIRED에 의해서 기존 활성화 트랜잭션에 참여하냐] 이 느낌인가요?
바깥 트랜잭션 O, 내부 호출 => 그냥 바깥 트랜잭션을 사용하고 있는 것입니다. (참여라는 말의 정의가 논리 트랜잭션이 새로 생겨 참여하느냐고 물어보신다면, 로깅으로 확인하셨듯이 참여하는 것은 아닙니다. 내부 호출 시, 트랜잭션 프록시를 거치지 않고 바로 호출되기 때문입니다. )
바깥 트랜잭션 O, 별도 클래스의 메서드(트랜잭션 O) => 이 때는 강의에서 학습하신 것처럼 트랜잭션 전파 기본 옵션인 REQUIRED에 의해 별도 클래스의 메서드의 트랜잭션이 바깥 트랜잭션에 참여하게 됩니다.
methodA에서 methodB를 내부 호출하더라도 methodA 자체적으로 트랜잭션이 활성화 되어있기 때문에 methodB는 그대로 해당 트랜잭션을 사용하는거군요
this.methodB() -> 그냥 활성화된 트랜잭션에 참여 (별도의 로그 X)
별도의 mainNestedService.methodB() -> 기본 REQUIRED이므로 methodA에서 활성화된 트랜잭션에 참여 (별도의 로그 O -> participate)
이렇게 이해하면 되는거 맞죠??