`

Spring Transaction 分析事务属性

 
阅读更多

众所周知的ACID属性: 
原子性(atomicity)、一致性(consistency)、隔离性(isolation)以及持久性(durability)。我们无法控制一致性、原子性以及持久性,但可以控制超时,设置事务的只读性以指定隔离级别。 
Spring在TransactionDefinition接口封装了所有这些设置。 

 

TransactionDefinition接口:

 

public interface TransactionDefinition {


	int PROPAGATION_REQUIRED = 0;


	int PROPAGATION_SUPPORTS = 1;

	
	int PROPAGATION_MANDATORY = 2;

	
	int PROPAGATION_REQUIRES_NEW = 3;


	int PROPAGATION_NOT_SUPPORTED = 4;

	
	int PROPAGATION_NEVER = 5;


	int PROPAGATION_NESTED = 6;


	
	int ISOLATION_DEFAULT = -1;


	int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;

	
	int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;


	int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;


	int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;


	int TIMEOUT_DEFAULT = -1;



	int getPropagationBehavior();


	int getIsolationLevel();


	int getTimeout();


	boolean isReadOnly();


	String getName();

}

 

getTimeout:返回一个事务必须完成的时间限制。 

isReadOnly:表示事务是否只读。 

getIsolationLevel:他对其他事务所看到的数据变化进行控制。 
事务隔离级别: 
隔离级别 说明 
ISOLATION_DEFAULT 默认级别(对大多数数据库来说就是ISOLATION_READ_COMMITTED) 
ISOLATION_READ_UNCOMMITTED 最低的隔离级别。事实上我们不应该隔离级别,因为在事务完成前,其他事务可以看到该事务所修改的数据。而在其他事务提交前,该事务也可以看到其他事务所做的修改。 
ISOLATION_READ_COMMITTED 大多数数据库的默认级别。在事务完成前,其他事务无法看到该事务所修改的数据。遗憾的是,在该事务提交后,你就可以查看其他事务插入活更新的数据。这意味着在事务的不同点上,如果其他事务修改数据,你会看到不同的数据。 
ISOLATION_REPEATABLE_READ 该隔离级别确保如果在事务中查询了某个数据集,你至少还能再次查询到相同的数据集,即使其他事务修改了所查询的数据。然而如果其他事务插入了新数据,你就可以查询到该新插入的数据。 
ISOLATION_SERIALIZABLE 代价最大、可靠性最高的隔离级别,所有的事务都是俺顺序一个接一个的执行。 

getPropagationBehavior:指定了当代码请求一个新的事务时Spring所做的事情。 
传播行为指: 
传播行为 说明 
PROPAGATION_REQUIRED 当前如果有事务,Spring就会使用该事务;否则会开始一个新事务。 
PROPAGATION_SUPPORTS 当前如果有事务,Spring就会使用该事务;否则不会开启一个新事务。 
PROPAGATION_MANDATORY 当前如果有事务,Spring就会使用该事务;否则会抛出异常。 
PROPAGATION_REQUIRES_NEW Spring总会开始一个新事务。如果当前有事务,则该事务挂起。 
PROPAGATION_NOT_SUPPORTED Spring不会执行事务中的代码。代码总是在非事务环境下执行,如果当期有事务,则该事务挂起。 
PROPAGATION_NEVER 即使当前有事务,Spring也会在飞事务环境下执行。如果当前有事务,则抛出异常。 
PROPAGATION_NESTED 如果当前有事务,则在嵌套事务中执行。如果没有,那么执行情况与PROPAGATION_REQUIRED一样。

 

TransactionStatus接口:

 

package org.springframework.transaction;

import java.io.Flushable;


public interface TransactionStatus extends SavepointManager, Flushable {


	boolean isNewTransaction();


	boolean hasSavepoint();

	
	void setRollbackOnly();

	
	
	boolean isRollbackOnly();


	@Override
	void flush();

	boolean isCompleted();

}

 

setRollbackOnly:将一个事务表示为不可提交的。

 

PlatformTransactionManager的实现: 

 

package org.springframework.transaction;


public interface PlatformTransactionManager {


	TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

	
	void commit(TransactionStatus status) throws TransactionException;

	
	void rollback(TransactionStatus status) throws TransactionException;

}

 

 


使用TransactionDefinition和TransactionStatus接口,创建并管理事务。
 
DataSourceTransactionManager控制着从DataSource中获得的JDBC Connection上的事务执行; 
HibernateTransactionManager控制着Hibernate session上的事务执行; 
JdoTransactionManager管理着JDO事务; 
JtaTransactionManager将事务管理委托给JTA。

 

JDBC:

 

<!-- 声明事务处理器 -->  
<bean id="transactionManager"  
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
    <property name="dataSource" ref="dataSource"></property>  
</bean>  
  
<!-- 声明事务通知 -->  
<tx:advice id="bookShopTx"  
    transaction-manager="transactionManager">  
    <tx:attributes>  
        <tx:method name="purchase"   
            propagation="REQUIRES_NEW"  
            isolation="READ_COMMITTED"  
            rollback-for="java.lang.ArithmeticException"/>  
    </tx:attributes>  
</tx:advice>  
  
<!-- 声明事务通知需要通知哪些类的那些方法, 即: 那些方法受事务管理 -->  
<aop:config>  
    <!-- 声明切入点 -->  
    <aop:pointcut expression="execution(* cn.partner4java.spring.transaction.BookShopService.*(..))"   
        id="txPointCut"/>  
          
    <!-- 把切入点和事务通知联系起来: 既声明一个增强器 -->  
    <aop:advisor advice-ref="bookShopTx" pointcut-ref="txPointCut"/>  
</aop:config>  

 

 

Hibernate:

 

<bean id="sessionFactory"  
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
    <property name="configLocation" value="classpath:hibernate.cfg.xml"></property>  
    <property name="dataSource" ref="dataSource"></property>      
</bean>  
  
<bean id="transactionManager"  
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
    <property name="sessionFactory" ref="sessionFactory"></property>      
</bean>  
  
<!-- 事务通知 -->  
<tx:advice id="txAdvice" transaction-manager="transactionManager">  
    <tx:attributes>  
        <tx:method name="new*" propagation="REQUIRED" isolation="DEFAULT" />  
        <tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT" />  
        <tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT" />  
        <tx:method name="delete*" propagation="REQUIRED" isolation="DEFAULT" />  
        <tx:method name="bulk*" propagation="REQUIRED" isolation="DEFAULT" />  
        <tx:method name="load*" propagation="REQUIRED" isolation="DEFAULT" read-only="true"/>  
        <tx:method name="get*" propagation="REQUIRED" isolation="DEFAULT" read-only="true"/>  
        <tx:method name="query*" propagation="REQUIRED" isolation="DEFAULT" read-only="true"/>  
        <tx:method name="find*" propagation="REQUIRED" isolation="DEFAULT" read-only="true"/>  
        <tx:method name="is*" propagation="REQUIRED" isolation="DEFAULT" read-only="true"/>  
          
        <tx:method name="*" propagation="SUPPORTS" isolation="DEFAULT" />  
    </tx:attributes>  
</tx:advice>  
<aop:config>  
        <aop:advisor pointcut="execution(* *..*service*.*(..))" advice-ref="txAdvice" />  
</aop:config>   
  
<context:component-scan base-package="com.bytter"></context:component-scan>  
  
<tx:annotation-driven/>  

 

JPA:

 

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">  
    <property name="dataSource" ref="dataSource" />  
    <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />  
    <property name="loadTimeWeaver">  
          <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>  
    </property>  
</bean>  
      
  <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">  
       <property name="entityManagerFactory" ref="entityManagerFactory"/>  
  </bean>  
    
  <tx:annotation-driven transaction-manager="transactionManager"/> 

 

 

基于 @Transactional 的声明式事务管理

除了基于命名空间的事务配置方式,Spring 2.x 还引入了基于 Annotation 的方式,具体主要涉及@Transactional 标注。@Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。如清单12所示:


清单12. 基于 @Transactional 的事务管理示例配置文件

@Transactional(propagation = Propagation.REQUIRED)
public boolean transfer(Long fromId, Long toId, double amount) {
return bankDao.transfer(fromId, toId, amount);
}

 

Spring 使用 BeanPostProcessor 来处理 Bean 中的标注,因此我们需要在配置文件中作如下声明来激活该后处理 Bean,如清单13所示:


清单13. 启用后处理Bean的配置

<tx:annotation-driven transaction-manager="transactionManager"/>

 

与前面相似,transaction-manager 属性的默认值是 transactionManager,如果事务管理器 Bean 的名字即为该值,则可以省略该属性。

虽然 @Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 小组建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。另外, @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。

基于 <tx> 命名空间和基于 @Transactional 的事务声明方式各有优缺点。基于 <tx> 的方式,其优点是与切点表达式结合,功能强大。利用切点表达式,一个配置可以匹配多个方法,而基于 @Transactional 的方式必须在每一个需要使用事务的方法或者类上用 @Transactional 标注,尽管可能大多数事务的规则是一致的,但是对 @Transactional 而言,也无法重用,必须逐个指定。另一方面,基于 @Transactional 的方式使用起来非常简单明了,没有学习成本。开发人员可以根据需要,任选其中一种使用,甚至也可以根据需要混合使用这两种方式。

如果不是对遗留代码进行维护,则不建议再使用基于 TransactionInterceptor 以及基于TransactionProxyFactoryBean 的声明式事务管理方式,但是,学习这两种方式非常有利于对底层实现的理解。

 

虽然上面共列举了四种声明式事务管理方式,但是这样的划分只是为了便于理解,其实后台的实现方式是一样的,只是用户使用的方式不同而已。

  • 大小: 74.7 KB
分享到:
评论

相关推荐

    springTransaction.rar

    这个名为"springTransaction.rar"的压缩包文件包含了一个关于Spring事务管理的小型示例,旨在演示如何使用Spring的事务传播机制来处理数据库操作,特别是转账功能的实现。 首先,让我们了解一下什么是事务。在...

    Spring在Transaction事务传播行为种类

    ### Spring中的Transaction事务传播行为种类详解 #### 一、引言 在开发基于Spring框架的应用程序时,事务管理是确保数据一致性的重要手段之一。Spring框架提供了丰富的事务管理功能,其中包括了事务传播行为...

    springtransaction 事务管理

    在实际项目中,`springtransaction`工程可能是包含了一个完整的示例,用于演示如何在MyEclipse环境中配置和使用Spring的事务管理功能。开发者可以通过导入此工程,学习和实践Spring事务管理的配置与使用,从而更好地...

    Spring 常用 Transaction Annotation

    当应用在类上时,该类的所有公共方法都将具有事务属性;如果应用于方法,只对被注解的方法生效。注解的属性包括 propagation(事务传播行为),isolation(隔离级别),readOnly(只读事务),timeout(超时时间),...

    spring-transaction.jar.zip

    "spring-transaction.jar"正是提供了Spring事务管理的类库,它包含了一系列用于处理事务的接口、类和配置元素,使得开发者能够方便地实现事务控制。 一、Spring 事务管理概述 Spring事务管理分为编程式事务管理和...

    Spring事务管理的jar包

    除了基本的事务控制,Spring还提供了丰富的事务属性,如传播行为(PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS等)、隔离级别(ISOLATION_DEFAULT、ISOLATION_READ_UNCOMMITTED等)和事务超时设置,允许开发者根据...

    实验 spring 声明事务

    声明式事务管理的原理在于,当满足特定条件(如上述配置中的方法匹配)时,Spring 会自动开始、提交或回滚事务,无需在业务逻辑代码中显式调用`beginTransaction()`、`commit()`或`rollback()`等事务管理API。...

    Spring自定义切面事务问题

    ### Spring自定义切面事务问题 #### 背景与挑战 在开发基于Spring框架的应用程序时,我们经常需要利用AOP(面向切面编程)来实现横切关注点(如日志记录、安全控制、事务管理等)的模块化处理。其中,事务管理是...

    spring-tx事务管理实例

    在分布式事务场景下,Spring提供了JtaTransactionManager,支持JTA(Java Transaction API)进行全局事务管理,可以跨越多个数据库或资源进行事务控制。此外,Spring还支持Atomikos、Bitronix等第三方JTA实现。 在...

    spring声明式事务处理demo

    Spring框架的声明式事务处理是其企业级应用中的核心特性之一,它允许开发者通过配置来管理事务,而无需在代码中显式地控制事务的开始、提交和回滚。这种方式极大地提高了代码的可读性和可维护性。在这个"spring声明...

    spring学习事务源码

    在源码分析中,我们可以看到当一个方法被@Transactional标记后,Spring会创建一个代理,这个代理在目标方法执行前后插入事务管理逻辑。在方法开始前,如果满足事务启动条件,就会调用`PlatformTransactionManager`的...

    spring几种事务配置详解【精】

    使用Java 5引入的注解,如`@Transactional`,可以直接在服务类或方法上标注,声明其事务属性。例如: ```java @Service public class UserService { @Transactional public void createUser(User user) { // ...

    Spring配置JTA事务管理

    4. 配置事务属性:Spring提供了`@Transactional`注解来标记需要进行事务管理的方法。你可以设置事务的隔离级别、传播行为、超时时间等属性。 5. 使用事务:在业务逻辑中,你可以通过编程式或声明式的方式来使用事务...

    Spring声明式事务配置管理方法

    Spring 声明式事务管理是Spring框架中的一个重要特性,它允许开发者在不编写任何事务管理代码的情况下,通过配置来管理事务。这种方式极大地简化了事务处理,并提高了代码的可维护性。以下是关于Spring声明式事务...

    Spring2.0 事务处理

    `tx:advice`定义了事务属性,如传播行为(`propagation`)、是否回滚(`rollback-for`)以及是否只读(`read-only`)。 `@Transactional`注解可以用于控制事务边界,例如: ```java @Service public class ...

    Spring基于XML方式配置事务

    这里我们主要探讨的是"Spring基于XML方式配置事务",这涉及到Spring的事务管理器、事务属性以及如何在XML配置文件中定义这些元素。 首先,Spring的事务管理分为两种模式:编程式事务管理和声明式事务管理。编程式...

    Spring的事务管理小案例

    案例中的"springStudy04_transaction"可能包含了一个使用Spring进行事务管理的简单应用程序,其中可能包括了数据库连接配置、数据访问对象(DAO)的实现以及事务控制的代码。你可以通过阅读源代码来了解如何在实际...

    springboot-transaction事务

    - 事务管理器(Transaction Manager):在Spring Boot中,如果检测到JPA或Hibernate,将会自动配置一个`PlatformTransactionManager`实例。 2. **JPA集成** - JPA是Java提供的ORM(Object-Relational Mapping)...

    Spring+JOTM 分布式事务管理

    声明式事务管理是通过在配置文件或注解中声明事务属性,如传播行为、隔离级别、超时和回滚规则,从而实现事务管理。这使得开发者无需在业务逻辑代码中手动管理事务的开始、提交和回滚。Spring的`...

    Spring事务类型祥解

    在Spring中,可以使用`@Transactional`注解的`propagation`属性配合`TransactionTemplate`进行更安全的编程式事务管理。 2. **声明式事务管理**: 声明式事务管理是Spring的核心特性之一,它通过AOP(面向切面编程...

Global site tag (gtag.js) - Google Analytics