본문 바로가기
SpringFramework | SpringBoot

스프링 Transactional 정리

by Lcoding 2023. 11. 10.
반응형

@Transactional


 @Slf4j
    static class CallService {
        //메서드 내부호출에서는 this.internal이 실행되므로 Transactional이 적용되지않는다.
        // 적용하려면 별도의 클래스로 분리하여야한다.

        public void external() {
            log.info("call external");
            printTxInfo();
            internal();
        }

        @Transactional
        public void internal() {
            log.info("call internal");
            printTxInfo();
        }

        private void printTxInfo() {
            boolean txActive = TransactionSynchronizationManager.isActualTransactionActive();
            log.info("tx active={}", txActive);
        }
    }


————>>>>————>>>>————>>>>————>>>>————>>>>————>>>>————>>>>————>>>>————>>>>

  @Slf4j
    @RequiredArgsConstructor
    static class CallService {
        //메서드 내부호출에서는 this.internal이 실행되므로 Transactional이 적용되지않는다.
        // 적용하려면 별도의 클래스로 분리하여야한다.

        private final InternalService internalService;

        public void external() {
            log.info("call external");
            printTxInfo();
            internalService.internal();
        }

//        @Transactional
//        public void internal() {
//            log.info("call internal");
//            printTxInfo();
//        }

        private void printTxInfo() {
            boolean txActive = TransactionSynchronizationManager.isActualTransactionActive();
            log.info("tx active={}", txActive);
        }
    }

    @Slf4j
    static class InternalService {
        @Transactional
        public void internal() {
            log.info("call internal");
            printTxInfo();
        }
        private void printTxInfo() {
            boolean txActive = TransactionSynchronizationManager.isActualTransactionActive();
            log.info("tx active={}", txActive);
        }
    }


public 메서드만 트랜잭션 적용
스프링의 트랜잭션 AOP 기능은 public 메서드에만 트랜잭션을 적용하도록 기본 설정이 되어있다. 
참고로 public 이 아닌곳에 @Transactional 이 붙어 있으면 예외가 발생하지는 않고, 트랜잭션 적용만 무시된다. 

스프링 초기화 시점에는 트랜잭션 AOP가 적용되지 않을 수 있다. 
왜냐하면 초기화 코드가 먼저 호출되고, 그 다음에 트랜잭션 AOP가 적용되기 때문이다. 
따라서 초기화 시점에는 해당 메서드에서 트랜잭션을 획득할 수 없다. 

가장 확실한 대안은 ApplicationReadyEvent 이벤트를 사용하는 것이다. 

  @EventListener(value = ApplicationReadyEvent.class)
  @Transactional
  public void init2() {
      log.info("Hello init ApplicationReadyEvent");
  }

----

언체크 예외는 롤백한다.
체크예외는 커밋한다.

예외 발생시 스프링 트랜잭션 AOP는 예외의 종류에 따라 트랜잭션을 커밋하거나 롤백한다.
언체크 예외인 RuntimeException , Error 와 그 하위 예외가 발생하면 트랜잭션을 롤백한다. 
체크 예외인 Exception 과 그 하위 예외가 발생하면 트랜잭션을 커밋한다.
물론 정상 응답(리턴)하면 트랜잭션을 커밋한다. 

 

반응형

loading