国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php框架 > 框架设计 > spring 事务详解

spring 事务详解

来源:程序员人生   发布时间:2016-12-15 10:11:22 阅读次数:3893次

1、甚么是事务

      事务是1系列的动作,它们综合在1起才是1个完全的工作单元,这些动作必须全部完成,如果有1个失败的话,那末事务就会回滚到最开始的状态。事务有4个特性ACID
  • 原子性(Atomicity):事务是1个原子操作,由1系列动作组成。事务的原子性确保动作要末全部完成,要末完全不起作用。
  • 1致性(Consistency):1旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于1致的状态,而不会是部份完成部份失败
  • 隔离性(Isolation):可能有许多事务会同时处理相同的数据,因此每一个事务都应当与其他事务隔离开来,避免数据破坏。
  • 持久性(Durability):1旦事务完成,不管产生甚么系统毛病,它的结果都不应当遭到影响。通常情况下,事务的结果被写到持久化存储器中。

2、spring事务管理器

      Spring其实不直接收理事务,而是提供了多种事务管理器。Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。接口中有3个方法

public interface PlatformTransactionManager { //根据事务定义TransactionDefinition,获得事务 TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; //提交事务 void commit(TransactionStatus status) throws TransactionException; //回滚事务 void rollback(TransactionStatus status) throws TransactionException; }
其中,TransactionDefinition是事务的1些基础信息,如超时时间,隔离级别,传播特性等;TransactionStatus是事务的状态,如是否是1个新事务,是不是被标记为回滚等。Spring针对不同的ORM提供的事务管理器,都是集成自AbstractPlatformTransactionManager,而AbstractPlatformTransactionManager又实现了PlatformTransactionManager。

         2.1 JDBC、Mybatis和ibatis事务管理器 
           如果利用程序中直接使用JDBC来进行持久化,需要配置JDBC事务管理器DataSourceTransactionManager,通过DataSource获得到java.sql.Connection来管理事务,调用连接的commit()方法来提交事务,一样,事务失败则通过调用rollback()方法进行回滚。

  • <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>
         2.2 Hibernate事务管理器
  • <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean>
         2.3 JPA事务管理器
  • <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean>

    通过entityManagerFactory属性指定需要事务管理的javax.persistence.EntityManagerFactory对象。还需要为entityManagerFactory对象指定jpaDialect属性,该属性所对应的对象指定了如何获得连接对象、开启事务、关闭事务等事务管理相干的行动

  • <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> …… <property name="jpaDialect" ref="jpaDialect"/> </bean> <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
    2.4 Java散布式事务管理器JTA
  • <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="userTransaction" ref="jotm" /> </bean>
  • <!-- JOTM实例 --> <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"> <property name="defaultTimeout" value="500000"/> </bean>

散布式事务通常是指多个数据源之间的实物,在tomcat下,是没有散布式事务的,不过可以借助于第3方软件jotm(Java Open Transaction Manager )和AtomikosTransactionsEssentials实现。

2.5 JDO事务管理器
  • <bean id="txManager" class="org.springframework.orm.jdo.JdoTransactionManager"> <property name="persistenceManagerFactory" ref="persistenceManagerFactory"/> </bean>
    通过persistenceManagerFactory属性指定需要事务管理的javax.jdo.PersistenceManagerFactory对象。
    具体可参考:http://hhhk.iteye.com/blog/2082714

    3、Spring事务的特性

    1、事务的传播行动  

    所谓事务的传播行动是指,如果在开始当前事务之前,1个事务上下文已存在,此时有若干选项可以指定1个事务性方法的履行行动。在TransactionDefinition定义中包括了以下几个表示传播行动的常量:

  • TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建1个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。 TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。 TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。 TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。 TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。 TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建1个新的事务,如果当前存在事务,则把当前事务挂起。 TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建1个新的事务。这是默许值。
    2、事务的隔离级别  

     隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了5个表示隔离级别的常量:

  • TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示1个事务可以读取另外一个事务修改但还没有提交的数据。该级别不能避免脏读,不可重复读和幻读,因此很少使用该隔离级别。 TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示1个事务只能读取另外一个事务已提交的数据。该级别可以避免脏读,这也是大多数情况下的推荐值。 TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示1个事务在全部进程中可以屡次重复履行某个查询,并且每次返回的记录都相同。该级别可以避免脏读和不可重复读。 TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务顺次逐一履行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以避免脏读、不可重复读和幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
    3、只读属性

      事务的第3个特性是它是不是为只读事务。如果事务只对后真个数据库进行该操作,数据库可以利用事务的只读特性来进行1些特定的优化。

    4、事务超时 

      由于事务可能触及对后端数据库的锁定,所以长时间的事务会没必要要的占用数据库资源。事务超时就是事务的1个定时器,在特定时间内事务如果没有履行终了,那末就会自动回滚,而不是1直等待其结束。

    5、回滚规则

      唆使spring事务管理器回滚1个事务的推荐方法是在当前事务的上下文内抛出异常。spring事务管理器会捕捉任何未处理的异常,然后根据规则决定是不是回滚抛出异常的事务。默许配置下,spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会致使事务回滚),而抛出checked异常则不会致使事务回滚。可以明确的配置在抛出那些异常时回滚事务,包括checked异常。也能够明肯定义那些异常抛出时不回滚事务。还可以编程性的通过setRollbackOnly()方法来唆使1个事务必须回滚,在调用完setRollbackOnly()后你所能履行的唯1操作就是回滚。

    6、事务状态

  • public interface TransactionStatus{ boolean isNewTransaction(); // 是不是是新的事物 boolean hasSavepoint(); // 是不是有恢复点 void setRollbackOnly(); // 设置为只回滚 boolean isRollbackOnly(); // 是不是为只回滚 boolean isCompleted; // 是不是已完成 }

    4、Spring支持的事务管理

    Spring提供了对编程式事务和声明式事务的支持,编程式事务允许用户在代码中精肯定义事务的边界,而声明式事务(基于AOP)有助于用户将操作与事务规则进行解耦。

    Spring配置文件中关于事务配置总是由3个组成部份,分别是DataSource、TransactionManager和代理机制这3部份,不管哪一种配置方式,1般变化的只是代理机制这部份。DataSource、TransactionManager这两部份只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。

    1、编程式事务

          Spring提供两种方式的编程式事务管理,分别是:使用TransactionTemplate和直接使用PlatformTransactionManager。

        1)采取TransactionTemplate和采取其他Spring模板,如JdbcTempalte和HibernateTemplate是1样的方法,它使用回调方法,把利用程序从处理获得和释放资源中摆脱出来。TransactionTemplate是线程安全的。
  • <!-- JDBC事务管理器 注意:事务管理器传的参数是数据源--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" scope="singleton"> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> <!-- 声明事务模板 --> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> </bean>
    public <T> T execute(TransactionCallback<T> action) throws TransactionException { if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) { return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action); } else { TransactionStatus status = this.transactionManager.getTransaction(this); T result; try { result = action.doInTransaction(status); } catch (RuntimeException ex) { // Transactional code threw application exception -> rollback rollbackOnException(status, ex); throw ex; } catch (Error err) { // Transactional code threw error -> rollback rollbackOnException(status, err); throw err; } catch (Exception ex) { // Transactional code threw unexpected exception -> rollback rollbackOnException(status, ex); throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception"); } this.transactionManager.commit(status); return result; } }
    可以看到transactionTemplate 的履行是在execute中的,所以
  • TransactionTemplate tt = new TransactionTemplate(); // 新建1个TransactionTemplate Object result = tt.execute( new TransactionCallback(){ public Object doTransaction(TransactionStatus status){ updateOperation(); return resultOfUpdateOperation(); } }); // 履行execute方法进行事务管理

    2)使用PlatformTransactionManager
      。。。

    2、声明式事务管理

        1)利用aop配置

    • <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" propagation="REQUIRED" /> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="interceptorPointCuts" expression="execution(* com.bluesky.spring.dao.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="interceptorPointCuts" /> </aop:config>
        2)声明式注解事务
    • <!-- 注解方式配置事物 --> <tx:annotation-driven transaction-manager="transactionManager" />
      3)使用拦截器
    • <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager" /> <!-- 配置事务属性 --> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <value>*Dao</value> </list> </property> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> </list> </property> </bean>


生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生