> php教程 > PHP开发 > 본문

스프링 트랜잭션 추상화

高洛峰
풀어 주다: 2016-11-22 15:17:07
원래의
1207명이 탐색했습니다.

1 Spring Framework 트랜잭션 관리 소개

포괄적인 트랜잭션 지원은 Spring 프레임워크를 사용하는 강력한 이유입니다. Spring 프레임워크는 다음과 같은 이점과 함께 트랜잭션 관리를 위한 일관된 추상화를 제공합니다.

Java Transaction API(JTA), JDBC, Hibernate, Java Persistence API(JPA)와 같은 다양한 트랜잭션 API에서 일관된 프로그래밍 모델 및 JDO(Java 데이터 개체).

선언적 트랜잭션 관리를 지원합니다.

복잡한 트랜잭션 API(예: JTA)보다 간단합니다.

Spring의 데이터 액세스 추상화와 완벽하게 통합됩니다.

Spring Framework 트랜잭션 지원 모델의 2가지 장점

전통적으로 Java EE 개발자에게는 전역 또는 로컬 트랜잭션이라는 두 가지 선택적 트랜잭션 관리 방법이 있으며 각각 고유한 제한 사항이 있습니다.

2.1 글로벌 트랜잭션

글로벌 트랜잭션을 사용하면 일반적으로 관계형 데이터베이스 및 메시지 대기열과 같은 여러 트랜잭션 리소스를 사용할 수 있습니다. 이 애플리케이션은 투박한 API인 JTA를 통해 전역 트랜잭션을 관리합니다. 또한 JTA UserTransaction은 일반적으로 JNDI에서 가져와야 합니다. 즉, JNDI를 사용해야 합니다. 분명히 전역 트랜잭션을 사용하면 애플리케이션 코드의 재사용이 제한됩니다. 왜냐하면 JTA는 일반적으로 애플리케이션 서버 환경에서만 사용할 수 있기 때문입니다.

과거에는 글로벌 트랜잭션을 사용하는 데 선호되는 방법이 EJB CMT(Container Managed Transactions)였습니다. CMT는 선언적 트랜잭션 관리입니다. EJB CMT는 관련 트랜잭션에 대한 JNDI 조회를 지우지만 EJB 자체는 JNDI를 사용해야 합니다. 트랜잭션을 제어하기 위해 Java 코드를 작성할 필요성이 대부분(전부는 아님) 제거됩니다. 중요한 단점은 CMT가 JTA와 애플리케이션 서버 환경을 번들로 제공한다는 것입니다. 동시에 EJB를 사용하여 비즈니스 로직을 구현하거나 적어도 트랜잭션 EJB Facade 내에서만 작동합니다.

2.2 로컬 트랜잭션

로컬 트랜잭션은 특정 리소스입니다. 예를 들어 트랜잭션은 JDBC 연결과 연결됩니다. 로컬 트랜잭션은 사용하기 쉽지만 여러 트랜잭션 리소스를 포괄할 수 없다는 큰 단점이 있습니다. 예를 들어, JDBC 연결을 사용하여 관리되는 트랜잭션은 글로벌 JTA 트랜잭션 내에서 실행될 수 없습니다. 애플리케이션 서버는 트랜잭션 관리를 담당하지 않기 때문에 리소스 전체의 정확성을 보장하지 않습니다. 또 다른 단점은 로컬 트랜잭션의 침입적인 프로그래밍 모델입니다.

2.3 Spring 프레임워크의 일관된 프로그래밍 모델

Spring은 글로벌 트랜잭션과 로컬 트랜잭션의 단점을 해결합니다. 이를 통해 개발자는 어떤 환경에서도 일관된 프로그래밍 모델을 사용할 수 있습니다. 개발자는 서로 다른 환경에서 서로 다른 트랜잭션 관리를 추상화하는 자신만의 코드만 작성하면 됩니다. Spring 프레임워크는 선언적 및 프로그래밍적 트랜잭션 관리를 제공합니다. 대부분의 사용자는 선언적 트랜잭션 관리를 선호하며 이 방법도 권장됩니다.

프로그래밍 방식의 트랜잭션 관리를 통해 개발자는 모든 기본 트랜잭션에서 실행할 수 있는 Spring 프레임워크 트랜잭션 추상화를 사용합니다. 선호하는 선언적 모델을 사용하면 개발자는 일반적으로 트랜잭션 관리 코드를 거의 또는 전혀 작성하지 않으므로 Spring Framework 트랜잭션 API 또는 기타 트랜잭션 API에 의존하지 않습니다.

3 Spring Framework 트랜잭션 추상화 이해

Spring 트랜잭션 추상화의 핵심은 트랜잭션 전략 개념입니다. 트랜잭션 전략은 org.springframework.transaction.PlatformTransactionManager 인터페이스를 통해 정의됩니다:

공용 인터페이스 PlatformTransactionManager {

TransactionStatus getTransaction(

TransactionDefinition 정의)

void commit(TransactionStatus 상태) throws TransactionException;

void 롤백(TransactionStatus 상태) throws TransactionException;

}

코드에서 프로그래밍 모델을 사용할 수 있지만 이는 주로 서비스 공급자 인터페이스(SPI)입니다. PlatformTransactionManager는 인터페이스이기 때문에 모의하고 스텁하기 쉽습니다. JNDI와 같은 조회 전략이 필요하지 않습니다. PlatformTransactionManager는 Spring IoC 컨테이너에 정의된 다른 객체처럼 구현됩니다. 이러한 이점으로 인해 JTA를 사용하는 경우에도 Spring Framework 트랜잭션을 추상화할 가치가 있습니다. JTA를 직접 사용하는 것보다 트랜잭션 코드를 테스트하기가 더 쉽습니다.

PlatformTransactionManager 인터페이스 메소드에서 발생한 TransactionException은 감지되지 않은 예외입니다(즉, java.lang.RuntimeException을 상속함). 거래 실패는 치명적입니다. 애플리케이션 코드가 트랜잭션 실패로부터 실제로 복구할 수 있는 드문 경우에 애플리케이션 개발자는 TransactionException을 포착하고 처리하도록 선택할 수 있습니다. 장점은 개발자가 이를 강제할 필요가 없다는 것입니다.

getTransaction(..) 메소드는 TransactionDefinition 매개변수를 사용하여 TransactionStatus 객체를 반환합니다. 반환된 TransactionStatus는 새 트랜잭션을 나타낼 수도 있고 일치하는 트랜잭션이 현재 호출 스택에 있는 경우 기존 트랜잭션을 나타낼 수도 있습니다. 실제로 이것은 후자의 경우입니다. Java EE 트랜잭션 컨텍스트와 마찬가지로 TransactionStatus는 실행 가능한 트랜잭션과 연관되어 있습니다.

TransactionDefinition 인터페이스 설명:

격리(트랜잭션 격리 수준): 트랜잭션 격리 수준입니다. 예를 들어 이 트랜잭션이 커밋되지 않은 다른 트랜잭션을 읽을 수 있습니까?

전파(트랜잭션 전파): 일반적으로 트랜잭션 범위 내에서 실행되는 모든 코드는 트랜잭션 내에서 실행됩니다. 그러나 트랜잭션 컨텍스트가 이미 존재할 때 트랜잭션 메서드 실행 동작을 지정하는 옵션이 있습니다. 예를 들어, 기존 트랜잭션(일반적인 상황)에서 코드가 계속 실행되거나 기존 트랜잭션이 일시 중지되고 새 트랜잭션이 생성될 수 있습니다.

트랜잭션 시간 초과: 트랜잭션이 만료되고 기본 트랜잭션을 통해 자동으로 롤백되기 전까지 트랜잭션이 실행되는 기간입니다.

읽기 전용 상태: 읽기 전용 트랜잭션은 코드가 데이터를 읽기만 하고 수정하지 않을 때 사용할 수 있습니다. 어떤 경우에는 읽기 전용 트랜잭션이 최적화에 도움이 됩니다(예: Hibernate를 사용할 때).

이러한 설정은 표준 거래 개념을 반영합니다. 이러한 기본 개념은 Spring Framework 또는 트랜잭션 관리 솔루션을 사용하는 데 필수적입니다.

TransactionStatus 인터페이스는 트랜잭션 코드가 실행 가능한 트랜잭션을 제어하고 트랜잭션 상태를 쿼리하는 간단한 방법을 제공합니다.

공용 인터페이스 TransactionStatus는 SavepointManager {

boolean을 확장합니다. isNewTransaction ();

boolean hasSavepoint();

void setRollbackOnly();

boolean isRollbackOnly();

void 플러시();

boolean isCompleted();

}

Spring에서 선언적 또는 프로그래밍적 트랜잭션 관리를 선택하는지에 관계없이 올바른 PlatformTransactionManager 구현을 정의하는 것은 필수적입니다. 일반적으로 종속성 주입을 통해 이 구현을 정의합니다.

PlatformTransactionManager는 일반적으로 작업 환경(JDBC, JTA, Hibernate 등)을 알아야 합니다. 다음은 로컬 PlatformTransactionManager를 정의하는 예입니다.

JDBC 데이터 소스 정의:

        destroy‐method="close" >

;

PlatformTransactionManager 정의는 DataSource 정의를 참조합니다.

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

Java EE 컨테이너에서 JTA를 사용하는 경우 JNDI 및 Spring의 JtaTransactionManager를 사용하여 컨테이너의 DataSource를 가져올 수 있습니다.

xmlns:xsi =" http://www.w3.org/2001/XMLSchema-instance"

xmlns:jee="http://www.springframework.org/schema/jee"

xsi :schemaLocation = "

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/spring-dans.xsd

🎜 > http://www.springframework.org/schema/jee

http://www.springframework.org/schema/jee/spring-jee.xsd">

JtaTransactionManager 컨테이너의 전역 트랜잭션 관리를 사용하므로 DataSource나 특정 리소스에 대해 알 필요가 없습니다.

Hibernate의 로컬 트랜잭션을 사용할 수도 있습니다. 이 경우, 당신은 당신의 애플리케이션 코드가 Hibernate Session 인스턴스를 얻기 위해 사용할 Hibernate의 LocalSessionFactoryBean을 정의할 필요가 있습니다.

이 경우 txManager Bean은 HibernateTransactionManager입니다. DataSourceTransactionManager가 DataSource를 참조해야 하는 것처럼, HibernateTransactionManager는 SessionFactory를 참조해야 합니다:

    

    

        

           org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml

        

    

    

        

            hibernate.dialect=${hibernate.dialect}

        

    

   

 如果你使用 Hibernate 및 Java EE容器管理 JTA事务,那么你只用使用JtaTransactionManager:

在所有这些情况下,应用程序代码不需要改变。你仅仅需要改变配置来改变如何管理事务。

4    동종 사용 사례

현재 상황과 동일하지 않은 사례와 함께 사용되는 사례는 없습니다.资源(例如,DataSourceTransactionManager链接DataSource,HibernateTransactionManager链接SessionFactory等等)。

4.1    高级同步方式

Spring의 高级模板基于持久化集成APIs或使用带有事务的本地ORM API——感知工厂bean或代理管理本地资源工厂。这些事务感知解决方案内part处理资源创建, 重用, 清理, 资源事务同步选项와 异常映射。因此,数据访问代码没有处些亻务,但可以关注不样板式持久化逻辑。통常,你使사용본지ORM API或通过使用JdbcTemplate获取模板。

4.2    低级同步方式

例如,DataSourceUtils(JDBC)、EntityManagerFactoryUtils(JPA)、SessionFactoryUtils(Hibernate)、PersistenceManagerFactory Utils(JDO)는 底层同步方式。当你想应用程序代码直接处理本地持久化APIs, 你使用这些类确保获取Spring框架管理的实例, 事务是(可选)동종의, 发生in进程中的异常正确映射一致性API。

例如,JDBC의 정보 아래에서 JDBC 방법으로 DataSource상위에서 사용 getConnection() 방법을 사용하면 Spring의 org.springframework.jdbc.datasource.DataSourceUtils:

연결 conn = DataSourceUtils.getConnection(dataSource) ;

如果已存이 실제 사건에서 발생하는 일은 없습니다.选)같은 일이 발생하면 后续에서 엇동사务중중용.

这种方式不需要Spring事务管理(事务同步是可选的),因此,无论你是否使用Spring管理事务你都佽用它。

当然,一旦你使用Spring JDBC支持、JPA支持或Hibernate支持,你通常不喜欢使用DataSourceUtils或其它的帮助类。

4.3    TransactionAwareDataSourceProxy

현재TransactionAwareDataSourceProxy类。这是目标DataSource代理,包装目标DataSource到感知Spring管理事务。为此,它类似于Java EE服务器提供的传统JNDI DataSource。

5    声明式事务管理

Spring框架的声明式事务管理让Spring side向切face编程(AOP)成为可能,尽管,Spring框架发布包以模板shape式自带事务切면代码,一般需要理解AOP。

5.1    이론Spring框架的声ming式事务实现

통통지(当前基于XML或注解).AOP联합사务元数据产生AOPTransaction, 使용액션인터셉터联适当的PlatformTransactionManager实现驱动事务环绕方法调用。

스프링 트랜잭션 추상화

5.2 선언적 트랜잭션 구현의 예

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http : //www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http : //www.springframework.org/schema/tx

                                                                                   > org/schema/aop/spring- aop.xsd "& gt;

& lt;! ;

                                                                                            'get'으로 시작하는 읽기 전용 메서드 -->

                                    ~                                                                       다른 방법에서는 기본 설정을 사용합니다 -->

 tx:advice> (..))"/>

    

 ​                                                                        ~ ,, ,                          ,,,, P,

                                   >

기본적으로 런타임 예외나 오류가 발생하는 경우에만 Spring 트랜잭션이 롤백됩니다. 확인된 예외로 인해 Spring 트랜잭션이 롤백되지는 않습니다.

트랜잭션 롤백에 대한 예외 유형을 명시적으로 구성할 수 있습니다.

   

거래가 롤오버되지 않는 예외 유형을 지정할 수도 있습니다.

                                                                              

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

.org/aop

config; : pointcut id = "defaultServiceOperation" 표현식 = "실행(*x.y.service.*service.*(..))"/& gt;

;> & Lt; (* x.y.service.ddl.DefaultDdlManager.*(..))"/>

   

                                                                                                             ~ > >                                 " / beans>

5.5 설정

기본 설정:

트랜잭션 전파 설정이 필수입니다

트랜잭션 격리 수준이 기본입니다

트랜잭션은 읽기/쓰기입니다

트랜잭션 시간 초과는 기본적으로 기본 트랜잭션 시스템의 시간 초과로 설정되거나 시간 초과가 지원되지 않는 경우 아무것도 설정되지 않습니다.

모든 RuntimeException이 롤백을 트리거합니다. 예외가 발생하지 않습니다.

태그에 포함된 기본 설정은 속성:

5.6 @Transactional 사용

주석 관리 활성화:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http:/ / www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http:/ / www.springframework.org/schema/tx

                                                                                    | -aop.xsd">

& lt; 속성 이름 =" dataSource "ref =" dataSource "/& gt; ;/bean & gt;

🎜>

서비스 선언 주석:

@ Transactional

공용 클래스 DefaultFooService는 FooService를 구현합니다. {

Foo getFoo(String fooName);

Foo getFoo(String fooName, String barName);

void insertFoo(Foo foo);

void updateFoo(Foo foo);

}

@Transactional 설정:

@Transactional의 다중 트랜잭션 관리자:

public class TransactionalService {

스프링 트랜잭션 추상화

@Transactional("order")

public void setSomething(String name) { ... }

@Transactional("account")

public void doSomething() { ... }

}

< ;bean id="transactionManager1"

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

. ..

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

...

@Target({ElementType.METHOD, ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Transactional("order")

public @ 인터페이스 OrderTx {

}

@Target({ ElementType.METHOD, ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Transactional ("account")

public @interface AccountTx {

}

5.7 트랜잭션 전파

PROPAGATION_REQUIRED

트랜잭션 전파를 PROPAGATION_REQUIRED로 설정할 때 각 방법에 대한 논리적 트랜잭션 범위를 생성합니다. 각 논리적 트랜잭션 범위는 롤백 상태를 독립적으로 결정할 수 있으며 외부 트랜잭션 범위 논리는 내부 트랜잭션 범위와 독립적입니다. 물론 표준 PROPAGATION_REQUIRED 사례에서는 이러한 모든 범위가 동일한 물리적 트랜잭션에 매핑됩니다. 따라서 내부 트랜잭션 범위에서 롤백 플래그를 설정하는 것만으로는 발생하는 외부 트랜잭션의 실제 커밋에 영향을 미치지 않습니다.

그러나 이 경우 내부 트랜잭션 범위가 롤백 전용 표시로 설정되어 있고 외부 트랜잭션은 롤백을 결정하지 않았으므로 롤백이 예상외입니다. 해당 UnexpectedRollbackException이 발생합니다.

PROPAGATION_REQUIRES_NEW

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

PROPAGATION_NESTED

여러 저장점으로 롤백할 수 있는 물리 트랜잭션을 사용합니다. 이 롤백을 통해 내부 트랜잭션 범위는 해당 범위의 롤백을 트리거하고 외부 트랜잭션은 일부 작업이 롤백된 경우에도 물리적 트랜잭션을 계속할 수 있습니다. 이 설정은 일반적으로 JDBC 저장점에 매핑되므로 JDBC 리소스 트랜잭션에만 사용할 수 있습니다.

6 프로그래밍 방식 트랜잭션 관리

Spring 프레임워크는 두 가지 유형의 프로그래밍 방식 트랜잭션 관리를 제공합니다.

TransactionTemplate 사용(권장)

PlatformTransactionManager를 사용하여 직접 구현

6.1 TransactionTemplate 사용

TransactionTemplate은 다른 Spring 템플릿(예: JdbcTemplate)과 동일한 방식으로 사용됩니다.

공용 클래스 SimpleService는 서비스를 구현합니다. {

private final TransactionTemplate transactionTemplate;

public SimpleService(PlatformTransactionManager transactionManager) {

Assert.notNull(transactionManager, "'transactionManager' 인수는 null이 아니어야 합니다.");

this.transactionTemplate = new TransactionTemplate(transactionManager);

}

public Object someServiceMethod() {

return transactionTemplate.execute(new TransactionCallback() {

public Object doInTransaction(TransactionStatus status) {

          updateOperation1();

                  return resultOfUpdateOperation2(); 🎜> }

}

반환 값이 없으면 TransactionCallbackWithoutResult 클래스를 사용합니다.

transactionTemplate.execute(new TransactionCallbackWithoutResult() {

protected void doInTransactionWithoutResult(TransactionStatus status) {

updateOperation1() ;

updateOperation2();

}

});

비즈니스 코드에서 롤백:

transactionTemplate.execute( new TransactionCallbackWithoutResult() {

protected void doInTransactionWithoutResult(TransactionStatus status) {

try {

updateOperation1();

updateOperation2 ();

} catch (SomeBusinessExeption ex) {

status.setRollbackOnly();

}

}

} ) ;

거래 설정 지정:

공개 클래스 SimpleService는 서비스 {

private final TransactionTemplate transactionTemplate;

public SimpleService(PlatformTransactionManager transactionManager) {

Assert.notNull( transactionManager, "'transactionManager' 인수는 null이 아니어야 합니다.");

this.transactionTemplate = new TransactionTemplate(transactionManager) ;

this.transactionTemplate.setIsolationLevel(

TransactionDefinition.ISOLATION_READ_UNCOMMITTED);

this.transactionTemplate.setTimeout(30); // 30초

}

}

Spring XML을 사용하여 TransactionTemplate 구성 :

class="org.springframework.transaction.support.TransactionTemplate">

6.2 PlatformTransactionManager 사용

DefaultTransactionDefinition def = new DefaultTransactionDefinition();

def.setName("SomeTxName");

def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

TransactionStatus status = txManager.getTransaction(def);

try {

// 비즈니스 로직 실행

} catch (MyException ex) {

txManager.rollback(status );

throw ex;

}

txManager.commit(status);

7 트랜잭션을 프로그래밍 방식으로 관리할지 아니면 선언적으로 관리할지 선택하시겠습니까?

거래 작업 수가 적은 경우 프로그래밍 방식의 거래 관리를 선택하세요.

8개의 트랜잭션 바인딩 이벤트

Spring 4.2부터 리스너 이벤트를 트랜잭션 단계에 바인딩할 수 있습니다.

@Component public class MyComponent {

@TransactionalEventListener

public void handlerOrderCreatedEvent(CreationEvent CreationEvent) {

. .

}

}

TransactionalEventListener 주석은 수신 트랜잭션 단계를 사용자 정의할 수 있도록 단계 속성을 노출합니다. 유효한 단계는 BEFORE_COMMIT, AFTER_COMMIT(기본값), AFTER_ROLLBACK 및 AFTER_COMPLETION입니다.


관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 추천
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿