@Transactional 주석없이 다른 메서드를 호출하는 @Transactional 메서드?


89

으로 표시된 Service 클래스의 메서드를 보았지만으로 표시 @Transactional되지 않은 동일한 클래스의 다른 메서드도 호출했습니다 @Transactional.

별도의 메서드에 대한 호출로 인해 응용 프로그램이 DB에 대한 별도의 연결을 열거 나 부모 트랜잭션을 일시 중단하는 등의 의미가 있습니까?

어노테이션이있는 다른 메소드에 의해 호출되는 어노테이션이없는 메소드의 기본 동작은 무엇입니까 @Transactional?

답변:


117

@Transactional트랜잭션 블록 내에 없는 메서드를 호출 하면 상위 트랜잭션이 새 메서드로 계속됩니다. 부모 메서드 (with @Transactional)와 동일한 연결을 사용하고 호출 된 메서드에서 발생하는 예외 (without) @Transactional는 트랜잭션 정의에 구성된대로 트랜잭션을 롤백합니다.

당신이 가진 메서드를 호출하는 경우 @Transactional와 방법에서 주석을 @Transactional동일한 인스턴스 내에서 다음 호출 방법 트랜잭션 동작은 트랜잭션에 영향을주지 않습니다. 그러나 트랜잭션 정의가있는 다른 메서드에서 트랜잭션 정의가있는 메서드를 호출하고 다른 인스턴스에있는 경우 호출 된 메서드의 코드는 호출 된 메서드에 제공된 트랜잭션 정의를 따릅니다.

스프링 트랜잭션 문서선언적 트랜잭션 관리 섹션에서 자세한 내용을 확인할 수 있습니다 .

Spring 선언적 트랜잭션 모델은 AOP 프록시를 사용합니다. 따라서 AOP 프록시는 트랜잭션 생성을 담당합니다. AOP 프록시는 인스턴스에있는 메서드가 인스턴스 외부에서 호출되는 경우에만 활성화됩니다.


봄 기본 동작입니까?
goe

예. 기본 동작입니다.
Arun P Johny 2011 년

2
@Tomasz 예. 그러나 다른 @Transactional 메서드에서 호출 된 메서드에서 트랜잭션 전파를 변경해도 효과가 없음을 언급해야합니다.
Fil

1
@Tomasz, 그것이 내가 말하는 의미였습니다 will follow the transaction definitions given in the called method. 그러나 호출이 동일한 개체 인스턴스에서 오는 경우에는 호출이 트랜잭션 유지 관리를 담당하는 aop 프록시를 통해 전파되지 않으므로 아무런 영향을 미치지 않습니다.
Arun P Johny 2011 년

5
@Filip, 그것은 완전히 정확하지 않습니다 @Transactional. 다른 객체 / 인스턴스 의 정의 로 메서드를 호출하면 호출하는 메서드가 다른 @Transactional속성을 가지고 있더라도 호출 된 메서드는 자체 트랜잭션 정의를 따릅니다.
Arun P Johny 2011 년

23
  • 이는 별도의 메서드에 대한 호출로 인해 응용 프로그램이 DB에 대한 별도의 연결을 열거 나 부모 트랜잭션을 일시 중단하는 등의 원인이됩니까?

그것은 전파 수준 에 따라 다릅니다 . 다음은 가능한 모든 레벨 입니다.

예를 들어 전파 수준이 NESTED 인 경우 현재 트랜잭션이 "일시 중지"되고 새 트랜잭션이 생성됩니다 ( 참고 : 중첩 트랜잭션의 실제 생성은 특정 트랜잭션 관리자에서만 작동 함 ).

  • @Transactional 어노테이션이있는 다른 메소드에 의해 호출되는 어노테이션이없는 메소드의 기본 동작은 무엇입니까?

기본 전파 수준 ( "동작"이라고 함)은 REQUIRED 입니다. @Transactional주석 이있는 (또는 XML을 통해 선언적으로 처리 된) "내부"메서드가 호출 된 경우 동일한 트랜잭션 내에서 실행됩니다. 예를 들어 "새로운 항목 없음"이 생성됩니다.


주석이없는 NOT_SUPPORTED의 하위 호출은 어떻습니까? NOT_Supported를 상속합니까 아니면 REQURED가 기본값이므로 새 트랜잭션을 열었습니까? 예 : f1에 대해서는 NOT_SUPPORTED, f2에 대해서는 non 주석이있는 f1.call () {f2 ()}.
Dave

8

@Transactional은 트랜잭션 경계 (시작 / 종료)를 표시하지만 트랜잭션 자체는 스레드에 바인딩됩니다. 트랜잭션이 시작되면 원래 메서드가 반환되고 트랜잭션이 커밋 / 롤백 될 때까지 메서드 호출간에 전파됩니다.

@Transactional 어노테이션이있는 다른 메소드가 호출되면 전파는 해당 어노테이션의 전파 속성에 따라 다릅니다.


세 가지 답변은 어느 정도 더 정확한지 확실하지 않지만 어느 정도 서로 충돌합니다.
에릭 왕

1
@EricWang 오늘이 시나리오를 테스트했으며 Arun P Johny 의 답변 (설명 포함) 이이 내부 호출 시나리오에 가장 정확 하다는 사실을 공유하고 싶었습니다 .
Vinay Vissh

3

내부 메서드가 @Transactional로 주석 처리되지 않은 경우 내부 메서드는 외부 메서드에 영향을줍니다.

내부 메서드도 @Transactional with으로 주석 처리 된 경우 REQUIRES_NEW다음이 발생합니다.

...
@Autowired
private TestDAO testDAO;

@Autowired
private SomeBean someBean;

@Override
@Transactional(propagation=Propagation.REQUIRED)
public void outerMethod(User user) {
  testDAO.insertUser(user);
  try{
    someBean.innerMethod();
  } catch(RuntimeException e){
    // handle exception
  }
}


@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void innerMethod() {
  throw new RuntimeException("Rollback this transaction!");
}

내부 메소드에는 주석이 추가되고 REQUIRES_NEWRuntimeException이 발생하므로 트랜잭션을 롤백하도록 설정하지만 외부 트랜잭션에는 영향을주지 않습니다. 내부 트랜잭션이 시작되면 외부 트랜잭션이 일시 중지되고 내부 트랜잭션이 종료 된 후 다시 시작됩니다. 그들은 서로 독립적으로 실행되므로 외부 트랜잭션이 성공적으로 커밋 될 수 있습니다.


1
초보자를 위해 명확히하기 위해 innerMethod ()는 outerMethod ()와 다른 빈 (일명 Spring 관리 Java Object)에 있어야합니다. 둘 다 동일한 빈에 있으면 innerMethod가 실제로 주석에 선언 된 트랜잭션 동작을 사용하지 않을 것이라고 생각합니다. 오히려 outerMethod () 선언에 선언 된 것을 사용합니다. 이 때문에 봄이의 @Transactional 주석 (사용되는 AOP, 처리하는 방법이다 docs.spring.io/spring/docs/3.0.x/spring-framework-reference/... )
johnsimer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.