트랜잭션 - 적용 위치

박찬우·2024년 2월 8일

스프링 DB

목록 보기
38/53

적용 위치

  • Test
@Slf4j
@SpringBootTest
public class TxLevelTest {

    @Autowired
    LevelService levelService;

    @Test
    void orderTest() {
        levelService.write();
        levelService.read();
    }

    @TestConfiguration
    static class TxApplyLevelConfig {
        @Bean
        LevelService levelService() {
            return new LevelService();
        }
    }

    @Slf4j
    @Transactional(readOnly = true)
    static class LevelService {

        @Transactional(readOnly = false)
        public void write() {
            log.info("call write");
            printTxInfo();
        }

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

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

            boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
            log.info("tx readOnly={}", readOnly);
        }
    }
}

  • @Transactional 의 규칙
    • 우선순위 규칙
      • LevelService 의 타입에 @Transactional(readOnly = true) 이 붙어있다.
      • write() : 해당 메서드에 @Transactional(readOnly = false) 이 붙어있다.
        • 이렇게 되면 타입에 있는 @Transactional(readOnly = true) 와 해당 메서드에 있는 @Transactional(readOnly = false) 둘 중 하나를 적용해야 한다.
        • 클래스 보다는 메서드가 더 구체적이므로 메서드에 있는 @Transactional(readOnly = false) 옵 션을 사용한 트랜잭션이 적용된다.
    • 클래스에 적용하면 메서드는 자동 적용
      • read() : 해당 메서드에 @Transactional 이 없다. 이 경우 더 상위인 클래스를 확인한다.
        • 클래스에 @Transactional(readOnly = true) 이 적용되어 있다. 따라서 트랜잭션이 적용되고 readOnly = true 옵션을 사용하게 된다. 참고로 readOnly=false 는 기본 옵션이기 때문에 보통 생략한다.@Transactional == @Transactional(readOnly=false) 와 같다
  • TransactionSynchronizationManager.isCurrentTransactionReadOnly
    • 현재 트랜잭션에 적용된 readOnly 옵션의 값을 반환한다.

인터페이스에 @Transactional 적용

  • 구체적인 것이 더 높은 우선순 위를 가진다
    1. 클래스의 메서드 (우선순위가 가장 높다.)
    2. 클래스의 타입
    3. 인터페이스의 메서드
    4. 인터페이스의 타입 (우선순위가 가장 낮다.)
  • 클래스의 메서드를 찾고, 만약 없으면 클래스의 타입을 찾고 만약 없으면 인터페이스의 메서드를 찾고 그래도 없으면 인 터페이스의 타입을 찾는다.
  • 인터페이스에 @Transactional 사용하는 것은 스프링 공식 메뉴얼에서 권장하지 않는 방법
    (가급적 구체 클래스에 사용)
profile
진짜 개발자가 되어보자

0개의 댓글