2016-06-08 1 views
1

Spring에서 @Transactional annotated 메소드를 사용할 때 주석이 달린 메소드가 기본 데이터베이스 트랜잭션의 성공적인 커밋과 동기화 되었습니까? @ Transactional annotated 메소드는 Spring에서 성공적인 커밋을 기다리는가?

(이것은 트랜잭션이 실제로 선택한 전파 방법에 따라 경우하지 않을 수있는, 복귀 후 커밋 것으로 가정한다.)

커밋 기다리는 기본 동작이 아닌 경우는, 거기에 어떤이다 구성 또는 다른 방법을 통해이를 활성화하는 방법은 무엇입니까?

내 질문에 대한 동기는 내가 신뢰할 수있는 "저장 및 전달"구현 타입 엔드 포인트에서만 호출의 효과를 안정적으로 저장하기 위해 최선을 다하고있다 후 클라이언트 에 대한 응답을 반환을하고자하는 것입니다. 이것은 @Transactional으로 가능합니까?

+1

, 그냥 방법과에서를 실행 끝나면 커밋되거나 롤백됩니다. –

답변

2

짧은 대답은 아니오입니다.이 메서드는 커밋을 기다리지 않습니다.

  • 트랜잭션 메소드를 호출하기 전에 존재 : 실제로 어떻게됩니까

    는 두 가지 요인에 따라 달라집니다?

  • 트랜잭션 전파가 어떻게 사용됩니까?

트랜잭션이 미리 존재하지 않으면 메소드를 호출하기 전에 새 트랜잭션이 생성되고 롤백으로 만 표시되지 않은 경우 Spring은 메소드가 반환 된 후 즉시 커밋하려고 시도합니다. 메소드가 커밋을 기다리지 않으면 커밋이 즉시 실행됩니다. 때문에 중첩 호출로, 트랜잭션 annoted 메서드를 호출 할 때, 실제 거래는 이미 봄 참조 설명서에서

추출 존재하는 동안

상황이 어려워 갈 :

전파 설정이 PROPAGATION_REQUIRED, 인 논리 트랜잭션 범위는 설정이 적용되는 각 메소드에 대해 작성됩니다. 이러한 각 논리적 트랜잭션 범위는 롤백 전용 상태를 개별적으로 결정할 수 있으며 외부 트랜잭션 범위는 내부 트랜잭션 범위와 논리적으로 독립적입니다. 물론 표준 PROPAGATION_REQUIRED 동작의 경우 이러한 모든 범위가 동일한 실제 트랜잭션에 매핑됩니다. 따라서 내부 트랜잭션 범위에 설정된 롤백 전용 마커는 실제로 외부 트랜잭션의 커밋 기회에 영향을줍니다.

PROPAGATION_REQUIRES와 달리 PROPAGATION_REQUIRES_NEW는 영향을받는 트랜잭션 범위마다 완전히 독립적 인 트랜잭션을 사용합니다. 이 경우 내부 물리적 트랜잭션은 다르기 때문에 내부 트랜잭션의 롤백 상태에 영향을받지 않는 외부 트랜잭션을 사용하여 독립적으로 커밋하거나 롤백 할 수 있습니다.

PROPAGATION_NESTED는 롤백 할 수있는 여러 세이브 포인트가있는 단일 물리적 트랜잭션을 사용합니다. 이러한 부분 롤백을 사용하면 내부 트랜잭션 범위에서 해당 범위에 대한 롤백을 트리거 할 수 있으며 일부 트랜잭션은 롤백되었지만 물리적 트랜잭션을 계속할 수 있습니다.

즉, PROPAGATION_REQUIRES_NEW를 제외하고는 포함 트랜잭션이 끝나기 전에 커밋을 시도하지 않습니다. 당신이 커밋 트랜잭션 annoted 방법의 종료 후 즉시 발생하려면

말했다 다르게, 당신은 PROPAGATION_REQUIRES_NEW에 전파를 설정해야합니다 : 그것은 기다리지 않습니다 @Transactional(propagation=Propagation.REQUIRES_NEW)

+0

고마워요! 그러나 확실한 것은 : REQUIRES_NEW를 사용해도 커밋은 * 주석 처리 된 메소드의 끝에 * 올 것입니다. 이 동작을 변경할 수있는 방법이 있습니까? 아니면 명시 적 트랜잭션을 사용해야합니까? – lxgr

+0

@lxgr : around advice 내에서 메소드가 * 캡슐화되었으므로 메소드가 실제로 호출되기 전에 트랜잭션이 시작되고 이후에 종료됩니다. 보다 세밀한 제어가 필요하다면, 실제 사용 사례를 상상할 수 없더라도 명시 적 트랜잭션 관리를 사용해야 할 것입니다. –

+0

REQUIRES_NEW를 사용하는 데 도움이되지 않습니다 ... –

0

@Transactional을 사용하지 않은 경우 어떻게 처리합니까?

UserTransaction utx = entityManager.getTransaction(); 

try { 
    utx.begin(); 

    businessLogic(); 

    utx.commit(); 
} catch(Exception ex) { 
    utx.rollback(); 
    throw ex; 
} 

@Transactional 실제로 당신을 위해 같은 일을 다음처럼 비슷한 코드 블록 될 것입니다. 그래서 당신은 당신의 비즈니스 로직 후에 처리된다는 것을 알 수 있습니다.

나는이 멋진 코드 blog을 복사했습니다. 이를 확인하면 자세한 내용을 알 수 있습니다.

관련 문제