이 기사의 주요 연구는 스프링 트랜잭션 전파와 그 구현 원칙이며, 이는 다음과 같이 소개됩니다.
Spring은 현재 편의성, 완전한 기능 및 사용하기 쉬운 덕분에 Java 개발을위한 사실적인 표준입니다. 개발 과정에서 DB 운영은 매우 일반적인 운영이며 DB와 관련하여 거래가 포함됩니다. 정상적인 거래 과정에서 트랜잭션을 알지 못하더라도 프로그램의 정상적인 실행에 부작용이 없습니다. 그러나 예외가 발생하고 트랜잭션이 제대로 처리되지 않으면 예기치 않은 결과가 발생할 수 있습니다. Spring은 거래 측면, 특히 선언적 거래의 출현 측면에서 다양한 운영을 캡슐화하여 개발을보다 편안하게 만들었습니다. Spring은 트랜잭션을 확장하고 여러 전파 속성의 정의를 지원하며,이 기사의 초점이기도합니다.
엄격하게 말할 수는 없지만, 거래는 여러 운영의 약어입니다. 이러한 작업은 적용되거나 그 중 어느 것도 적용되지 않습니다 (실행되지 않는 것과 동일). 일반적인 작동 프로세스는 다음과 같이 단순화됩니다.
{Connection conn = getConnection (); // 일부 데이터베이스 작업을 수행} catch (예외 e) {conn.rollback ();} 마지막으로 {conn.close ();}위의 코드에서 몇 가지 문제를 볼 수 있습니다.
Spring은 선언적 거래를 제공하므로 기본 계층의 특정 구현에주의를 기울일 필요가 없으며 기본 계층의 다양한 구현 세부 사항을 차단합니다. Spring은 여러 복잡한 사업에 의한 거래의 미세한 제어를 지원하기 위해 거래의 전파 속성을 제공하고 선언 거래와 결합하여 주요 거래 도구가되었습니다.
TransactionDefinition 클래스에서 Spring은 6 개의 전파 특성을 제공하며 간단한 예제로 설명됩니다.
따뜻한 알림 : 현재 트랜잭션에 합류 한 다음과 같은 언급 된 것은 하단에서 동일한 연결을 사용하는 것을 말하지만 트랜잭션 상태 객체를 재현 할 수 있으며 영향을 미치지 않습니다. 이 기사는 현재 하나의 트랜잭션 만 있다고 언급했는데, 이는 기본 연결이 공유되고 있으며, 얼마나 많은 트랜잭션 상태 개체 (TransactionStatus)가 생성되는지는 신경 쓰지 않습니다.
설명 : 거래가 이미 존재하는 경우 거래에 가입하십시오. 거래가없는 경우 거래를 작성하십시오. 이것은 기본 전파 속성 값입니다.
작은 예를 보자. 코드는 다음과 같습니다.
@transactionalPublic void service () {servicea (); serviceb ();}@transactionalServicea ();@transactionalServiceb ();Servicea 및 ServiceB는 둘 다 거래를 선언합니다. 기본적으로 propagation = propagation_required. 전체 서비스 호출 프로세스 중에는 하나의 공유 거래 만 있습니다. 예외가 발생하면 모든 작업이 롤백됩니다.
설명 : 거래가 이미 존재하는 경우 거래에 가입하십시오. 그렇지 않으면 소위 빈 트랜잭션이 생성됩니다 (거래 실행이없는 것으로 간주 될 수 있음).
작은 예를 보자. 코드는 다음과 같습니다.
public void service () {servicea (); 새로운 runtimeexception ();}@transactional (propagation = propagation.supports) servicea ();Servicea가 실행될 때는 현재 거래가 없으므로 서비스에 예외가 발생하면 Servicea가 롤백을 유발하지 않습니다.
또 다른 작은 예를 살펴 보겠습니다. 코드는 다음과 같습니다.
public void service () {servicea ();}@transactional (propagation = propagation.supports) servicea () {do sql 1 1/0; SQL 2}Servicea는 실행할 때 트랜잭션이 없기 때문에 현재 기본 데이터 소스 DefaultAutoCommit = true 인 경우 SQL1이 효과적입니다. defaultAutoCommit = false 인 경우 SQL1이 유효하지 않습니다. 서비스에 @transactional 태그가있는 경우 Servicea는 서비스 거래를 공유합니다 (더 이상 DefaultAutoCommit에 의존하지 않음). 현재 Servicea는 모두 롤백됩니다.
설명 : 거래는 현재 존재해야합니다. 그렇지 않으면 예외가 발생합니다.
작은 예를 보자. 코드는 다음과 같습니다.
public void service () {serviceb (); servicea ();} serviceb () {do sql} @transactional (propagation = profagation.mandatory) servicea () {do sql}이 경우 서비스 실행은 예외가 발생합니다. defaultAutoCommit = true 인 경우 ServiceB는 롤백되지 않습니다. defaultAutoCommit = false 인 경우 ServiceB Execution이 유효하지 않습니다.
참고 : 거래가 현재 존재하는 경우, 먼저 현재 트랜잭션 관련 컨텐츠를 엔티티로 캡슐화 한 다음 새 거래를 재현 하고이 엔티티를 매개 변수로 받아들이고 트랜잭션 복구에 사용하십시오. 더 무거운 진술은 현재 거래를 중단하고 (거래가 필요하지 않음) 새로운 거래를 만드는 것입니다. 이 경우 두 거래 사이에는 의존성이 없으며 새 트랜잭션을 다시 롤백 할 수 있지만 외부 트랜잭션은 계속 실행됩니다.
작은 예를 보자. 코드는 다음과 같습니다.
@transactionalPublic void service () {serviceb (); try {servicea (); } catch (예외 e) {}} serviceb () {do sql} @transactional (propagation = propagation.requires_new) servicea () {do sql 1 1/0; SQL 2}서비스 인터페이스를 호출 할 때 Servicea는 Eledult_new를 사용하므로 새로운 트랜잭션이 생성됩니다. 그러나 Servicea는 런타임 예외를 던지기 때문에 Servicea는 롤백됩니다. 서비스 방법에서 예외가 잡히므로 Service는 정상적으로 제출됩니다. 시도 시도 ... 서비스의 코드 캐치 코드가 필요합니다. 그렇지 않으면 서비스가 예외를 던져서 ServiceB가 롤백됩니다.
참고 : 거래가 현재 존재하는 경우 현재 거래를 중단 한 다음 새로운 방법이 트랜잭션이없는 환경과 스프링 트랜잭션이없는 환경에서 실행됩니다.
작은 예를 보자. 코드는 다음과 같습니다.
@transactionalPublic void service () {serviceb (); servicea ();} serviceb () {do sql} @transactional (propagation = propagation.not_supported) servicea () {do sql 1 1/0; SQL 2}서비스 방법이 호출되면 Servicea 방법의 1/0 코드가 실행될 때 예외가 발생합니다. Servicea는 트랜잭션이없는 환경에 있기 때문에 SQL1이 효과적인 지 여부는 DefaultAutocommit의 값에 따라 다릅니다. DefaultAutoCommit = true 일 때 SQL1은 효과적이지만 서비스가 예외를 던지기 때문에 ServiceB가 롤백됩니다.
설명 : 거래가 현재 존재하는 경우 예외가 발생하면 트랜잭션이없는 환경에서 코드가 실행됩니다.
작은 예를 보자. 코드는 다음과 같습니다.
public void service () {serviceb (); servicea ();} serviceb () {do sql} @transactional (propagation = propagation.never) servicea () {do sql 1 1/0; SQL 2}위의 예제가 서비스를 호출하면 defaultAutoCommit = true 인 경우 Service Method 및 Servicea의 SQL1이 적용됩니다.
참고 : 거래가 현재 존재하는 경우 SavePoint 기술을 사용하여 현재 트랜잭션 상태를 저장 한 다음 기본 계층이 연결을 공유합니다. 중첩 내에서 오류가 발생하면 SavePoint 상태 자체로 롤백됩니다. 외부에 의해 예외가 발생하는 한, 임베디드 비즈니스에 의해 방해받지 않고 외부 거래를 계속할 수 있습니다. 그러나 외부 거래에 의해 예외가 발생하면 전체 대규모 트랜잭션이 롤백됩니다.
참고 : Spring Configuration Transaction Manager는 아래와 같이 NestedTransactionallowed = true를 적극적으로 지정해야합니다.
<bean id = "datatransactionManager"> <속성 이름 = "dataSource"ref = "dataDatasource" /> <property name = "nestEdtransactionAllowed"value = "true" /> < /bean>
작은 예를 참조하십시오. 코드는 다음과 같습니다.
@transactionalPublic void service () {servicea (); try {serviceb (); } catch (예외 e) {}} servicea () {do sql} @transactional (propagation = propagation.nested) servicb () {do sql1 1/0; sql2} do}ServiceB는 임베디드 서비스이며 런타임 예외가 내부적으로 발생하므로 ServiceB는 롤백됩니다. 서비스에서 예외가 발생 했으므로 Servicea는 정상적으로 제출할 수 있습니다.
다른 예를 살펴 보겠습니다. 코드는 다음과 같습니다.
@transactionalPublic void service () {servicea (); serviceb (); 1/0;}@transactional (propagation = propagation.nested) servicea () {do sql} serviceb () {do sql}서비스가 예외를 던지므로 전체 서비스 방법이 롤백됩니다. (이것은 propagation_requires_new와 다릅니다. 중첩 모드 하에서 내장 된 서비스는 외부 거래의 예외에 의해 롤백됩니다.)
위의 예는 Spring Transactions에서 제공하는 몇 가지 전파 속성을 보여줍니다. 비즈니스에 의해 결정될 수있는 다양한 비즈니스 요구를 충족시키는 데 사용됩니다. 다음으로, 스프링의 가장 중요한 기술 종속성이 이러한 전파 속성을 구현하는 것을 살펴 보겠습니다. 이 섹션에는 Propagation_Requires_new 및 Propagation.nested가 각각 간단한 설명을 위해 나열되어 있습니다.
다음 코드 호출 :
@transactionalPublic void service () {serviceb (); try {servicea (); } catch (예외 e) {}}@transactional (propagation = propagation.requires_new) servicea () {do sql 1 1/0; do sql 2} serviceb () {do sql}실행 회로도는 다음과 같습니다.
에이. 트랜잭션 상태 객체를 만들고, 새 연결을 받고, 자동 커밋을 재설정하고, 페치 크기, 타임 아웃 및 기타 연결 속성을 재설정하십시오.
비. ThreadLocal 변수에 연결을 바인딩하십시오
기음. 현재 트랜잭션이 보류, 현재 트랜잭션 상태 개체, 연결 및 기타 정보를 SelfedRessources 객체로 캡슐화하여 복구에 사용할 수 있습니다.
디. 새 트랜잭션 상태 객체를 만들고, 새 연결을 다시 찍고, 자동 커밋, 페치 크기, 타임 아웃 및 기타 새로운 연결 속성을 재설정하십시오. 동시에 트랜잭션 복구를 위해 SelsendedResources 객체를 저장하고 ThreadLocal 변수에 새 연결을 바인딩하십시오 (오버 곡선 작동).
이자형. 예외를 잡고, ThreadLocal에서 연결을 롤백하고, 연결 매개 변수를 복원하고, 연결을 닫고, SelsedRessources를 복원하십시오.
에프. ThreadLocal 변수 (ServiceB를 제출하게 함)에 연결을 제출하고 연결 매개 변수를 복원하고 연결을 닫고 데이터 소스에 연결을 반환합니다.
따라서 프로그램 실행 결과는 Servicea가 롤백되고 Service가 성공적으로 제출된다는 것입니다.
다음 코드 호출 :
@transactionalPublic void service () {servicea (); try {serviceb (); } catch (예외 e) {}} servicea () {do sql} @transactional (propagation = propagation.nested) servicb () {do sql1 1/0; sql2} do}실행 회로도는 다음과 같습니다.
에이. 트랜잭션 상태 객체를 만들고, 새 연결을 받고, 자동 커밋을 재설정하고, 페치 크기, 타임 아웃 및 기타 연결 속성을 재설정하십시오.
비. ThreadLocal 변수에 연결을 바인딩하십시오
기음. 현재 트랜잭션 상태 객체의 사용을 표시하고, ThreadLocal Connection 객체를 얻고, 현재 연결의 저장 포인트를 저장하며, 예외 복구에 사용됩니다. 현재 SavePoint는 Servicea가 실행 된 후 상태입니다.
디. 트랜잭션 롤백에 대한 예외를 잡고 SavePoint를 사용하십시오. ServiceB 방법의 모든 실행은 적용되지 않습니다
이자형. ThreadLocal에서 연결 객체 가져 오기, 트랜잭션 제출, 연결 속성 복원, Close Connection
기본 데이터 소스를 기반으로 Spring은 ResidLocal, SavePoint 및 기타 기술 포인트를 사용하여 다양한 트랜잭션 전파 속성을 실현하여 다양한 복잡한 서비스의 구현을 용이하게합니다. 전파 속성의 원리를 이해 함으로써만 스프링 트랜잭션을 더 잘 제어 할 수 있습니다. 스프링 롤백 거래는 예외의 캡처에 의존합니다. 기본적으로 트랜잭션은 runtimeexception 및 오류가 발생하는 경우에만 롤백됩니다. 물론 구성 할 수 있습니다. 자세한 내용은 @transactional 주석을 확인할 수 있습니다.
Spring의 선언적 거래는 우리에게 편의를 제공합니다. 이 무기를 잘 활용하려면 여전히 근본적인 원칙을 이해해야합니다. 이 기사는 봄 거래의 빙산의 일각 일뿐입니다. 독자는이 기준으로 깊이 탐구 할 수 있습니다.
위는 스프링 트랜잭션 전파 및 구현 원리에 대한이 기사의 모든 내용입니다. 모든 사람에게 도움이되기를 바랍니다. 관심있는 친구는이 사이트의 다른 관련 주제를 계속 참조 할 수 있습니다. 단점이 있으면 메시지를 남겨 두십시오. 이 사이트를 지원해 주신 친구들에게 감사드립니다!