ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • spring Transactional? javax Transactional?
    카테고리 없음 2023. 4. 20. 09:52
    @Transactional 스프링을 개발하다보면 어노테이션으로 트랜잭션처리를 많이 한다. 아주 좋은 어노테이션이다. 근데 한가지 궁금한게 생겼다. IDE로 자동완성을 하다보면 두가지가 나온다. javax.transaction 패키지의 Transactional 또 하나는 Spring Transactional이다. 이 두가지의 차이점이 궁금하였다. 그래서 테스트를 시작했다. 일단 Spring boot로 테스트를 해보았다. spring boot 1.4M2 로 테스트를 하였는데 똑같이 AOP도 동작하고 rollback도 동작하였다. 엥 그럼 뭐가 다른거지? 이것 저것 해봤는데 AOP와 롤백이 동작하였다. 다른게 존재 하지 않았다. 물론 Transactional 속성 값은 다르겠지만 롤백 자체가 되는건 스프링에서 관리를 해준다는 뜻 같았다. 그래서 한번 살펴 보았다. AOP가 동작할 때 소스를 보았다. org.springframework.transaction.annotation.AnnotationTransactionAttributeSource 클래스를 보면 아래와 같은 생성자가 존재 한다.
    public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
      this.publicMethodsOnly = publicMethodsOnly;
      this.annotationParsers = new LinkedHashSet<TransactionAnnotationParser>(2);
      this.annotationParsers.add(new SpringTransactionAnnotationParser());
      if (jta12Present) {
        this.annotationParsers.add(new JtaTransactionAnnotationParser());
      }
      if (ejb3Present) {
        this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
      }
    }
    
    저기 보면 SpringTransactionAnnotationParser 은 디폴트로 등록하고 javax.transaction.Transactional 이 존재 하면 등록한다 마찬가지로 ejb3 transaction 도 존재 하면 등록한다. 그래서 저게 모냐 한번 따라가 봤다. 아래는 SpringTransactionAnnotationParser 클래스다.
    /**
     * Strategy implementation for parsing Springs {@link Transactional} annotation.
     *
     * @author Juergen Hoeller
     * @since 2.5
     */
    
    위와 같은 주석이 되어있다. Transactional 어노테이션을 파싱하는 클래스 인 듯하다.
    @Override
    public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
      AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, Transactional.class);
      if (attributes != null) {
        return parseTransactionAnnotation(attributes);
      }
      else {
        return null;
      }
    }`
    
    실제 Spring의 Transactional 달린 메서드 혹은 클래스를 파싱한다. JtaTransactionAnnotationParser 클래스도 살펴봤다.
    @Override
    public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
        AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, javax.transaction.Transactional.class);
        if (attributes != null) {
            return parseTransactionAnnotation(attributes);
        }
        else {
            return null;
        }
    }
    
    비슷하다 javax.transaction.Transactional 어노테이션이 달린 메서드 혹은 클래스를 파싱한다. 그래서 비슷한 동작을 하지 않나 싶다. 그런데 주석에 이렇게 나와 있다.
    /**
     * Strategy implementation for parsing JTA 1.2s {@link javax.transaction.Transactional} annotation.
     *
     * @author Juergen Hoeller
     * @since 4.0
     */
    
    4.0 부터 저 클래스가 만들어 졌다. 그럼 4.0 부터 되었으니 4.0 이하 버전은 안될까? 그래서 테스틀 해봤다. 일단 3.2.3 으로 테스트를 해봤는데 클래스 자체가 없다. 4.0 부터 추가 된게 맞다. 그래서 혹시 어떻게 되나 궁금해서 테스트를 시작했다.
    //  아래는 롤백이 된다.
    //  @org.springframework.transaction.annotation.Transactional
    //  롤백이 되지 않는다
    @javax.transaction.Transactional
    public AccountTest save() {
      AccountTest accountTest = new AccountTest();
      accountTest.setName("wonwoo");
      accountRepository.save(accountTest);
      if (true) {
        throw new RuntimeException();
      }
      return accountTest;
    }
    
    위와 같이 3.2.3에서 테스트 한 결과 롤백이 되지 않았다. 그러므로 4.0 이하를 쓰는 개발자들은 org.springframework.transaction.annotation.Transactional을 꼭 써야된다. Spring boot를 쓰는 개발자는 되도록이면 스프링에 있는 트랜잭션 어노테이션을 쓰자 컨트롤 할 수 있는 속성이 더 많다.

    댓글

Designed by Tistory.