Spring 事务相关

    Spring对事务的解决办法分为2种:编程式实现事务;AOP配置声明式解决方案。


    编程式事务是不推荐的,只有在为了深入理解Spring事务管理时才需要学习编程式事务使用。


    Spring声明式事务,让我们从复杂的事务处理中得到解脱。使得我们再也无需要去处理获得连接、关闭连接、事务提交和回滚等这些操作。再也无需要我们在与事务相关的方法中处理大量的try…catch…finally代码。

    我们在使用Spring声明式事务时,有一个非常重要的概念就是事务属性。事务属性通常由事务的传播行为,事务的隔离级别,事务的超时值和事务只读标志组成。我们在进行事务划分时,需要进行事务定义,也就是配置事务的属性。


    http://www.blogjava.net/robbie/archive/2009/04/05/264003.html

    在Spring的配置文件中,关于事务的配置总体上由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。

    DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。

    根据代理机制的不同,总结了五种Spring事务的配置方式,具体如下图:(图片更正:JTA配置,JtaTransactionManager)

Spring事务配置 (2)


    第一种方式:每个Bean都有一个代理

<? xml version="1.0" encoding="UTF-8" ?>
< beans  xmlns ="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context
="http://www.springframework.org/schema/context"
    xmlns:aop
="http://www.springframework.org/schema/aop"
    xsi:schemaLocation ="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
>

    
< bean  id ="sessionFactory"   
            class
="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >   
        
< property  name ="configLocation"  value ="classpath:hibernate.cfg.xml"   />   
        
< property  name ="configurationClass"  value ="org.hibernate.cfg.AnnotationConfiguration"   />
    
</ bean >   

    
<!--  定义事务管理器(声明式的事务)  -->   
    
< bean  id ="transactionManager"
        class
="org.springframework.orm.hibernate3.HibernateTransactionManager" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >
    
    
<!--  配置DAO  -->
    
< bean  id ="userDaoTarget"  class ="com.bluesky.spring.dao.UserDaoImpl" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >
    
    
< bean  id ="userDao"   
        class
="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" >   
           
<!--  配置事务管理器  -->   
           
< property  name ="transactionManager"  ref ="transactionManager"   />      
        
< property  name ="target"  ref ="userDaoTarget"   />   
         
< property  name ="proxyInterfaces"  value ="com.bluesky.spring.dao.GeneratorDao"   />
        
<!--  配置事务属性  -->   
        
< property  name ="transactionAttributes" >   
            
< props >   
                
< prop  key ="*" > PROPAGATION_REQUIRED </ prop >
            
</ props >   
        
</ property >   
    
</ bean >   
</ beans >

    第二种方式:所有Bean共享一个代理基类

<? xml version="1.0" encoding="UTF-8" ?>
< beans  xmlns ="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context
="http://www.springframework.org/schema/context"
    xmlns:aop
="http://www.springframework.org/schema/aop"
    xsi:schemaLocation
="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
>

    
< bean  id ="sessionFactory"   
            class
="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >   
        
< property  name ="configLocation"  value ="classpath:hibernate.cfg.xml"   />   
        
< property  name ="configurationClass"  value ="org.hibernate.cfg.AnnotationConfiguration"   />
    
</ bean >   

    
<!--  定义事务管理器(声明式的事务)  -->   
    
< bean  id ="transactionManager"
        class
="org.springframework.orm.hibernate3.HibernateTransactionManager" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >
    
    
< bean  id ="transactionBase"   
            class
="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"   
            lazy-init
="true"  abstract ="true" >   
        
<!--  配置事务管理器  -->   
        
< property  name ="transactionManager"  ref ="transactionManager"   />   
        
<!--  配置事务属性  -->   
        
< property  name ="transactionAttributes" >   
            
< props >   
                
< prop  key ="*" > PROPAGATION_REQUIRED </ prop >   
            
</ props >   
        
</ property >   
    
</ bean >     
   
    
<!--  配置DAO  -->
    
< bean  id ="userDaoTarget"  class ="com.bluesky.spring.dao.UserDaoImpl" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >
    
    
< bean  id ="userDao"  parent ="transactionBase"   >   
        
< property  name ="target"  ref ="userDaoTarget"   />    
    
</ bean >
</ beans >

第三种方式:使用拦截器

<? xml version="1.0" encoding="UTF-8" ?>
< beans  xmlns ="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context
="http://www.springframework.org/schema/context"
    xmlns:aop
="http://www.springframework.org/schema/aop"
    xsi:schemaLocation ="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
>

    
< bean  id ="sessionFactory"   
            class
="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >   
        
< property  name ="configLocation"  value ="classpath:hibernate.cfg.xml"   />   
        
< property  name ="configurationClass"  value ="org.hibernate.cfg.AnnotationConfiguration"   />
    
</ bean >   

    
<!--  定义事务管理器(声明式的事务)  -->   
    
< bean  id ="transactionManager"
        class
="org.springframework.orm.hibernate3.HibernateTransactionManager" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >  
   
    
< 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 >   
  
    
<!--  配置DAO  -->
    
< bean  id ="userDao"  class ="com.bluesky.spring.dao.UserDaoImpl" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >
</ beans >

第四种方式:使用tx标签配置的拦截器

<? xml version="1.0" encoding="UTF-8" ?>
< beans  xmlns ="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context
="http://www.springframework.org/schema/context"
    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-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
>

    
< context:annotation-config  />
    
< context:component-scan  base-package ="com.bluesky"   />

    
< bean  id ="sessionFactory"   
            class
="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >   
        
< property  name ="configLocation"  value ="classpath:hibernate.cfg.xml"   />   
        
< property  name ="configurationClass"  value ="org.hibernate.cfg.AnnotationConfiguration"   />
    
</ bean >   

    
<!--  定义事务管理器(声明式的事务)  -->   
    
< bean  id ="transactionManager"
        class
="org.springframework.orm.hibernate3.HibernateTransactionManager" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >

    
< 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 >       
</ beans >

*****************************************************************************************************

XML形式的事务配置<tx:method >的属性详解 

属性
类型
默认值
说明
propagationPropagation枚举REQUIRED事务传播属性
isolationisolation枚举DEFAULT(所用数据库默认级别)事务隔离级别
readOnlybooleanfalse是否才用优化的只读事务
timeoutint-1超时(秒)
rollbackForClass[]{}需要回滚的异常类
rollbackForClassNameString[]{}需要回滚的异常类名
noRollbackForClass[]{}不需要回滚的异常类
noRollbackForClassNameString[]{}不需要回滚的异常类名


*readOnly  
事务属性中的readOnly标志表示对应的事务应该被最优化为只读事务。如果值为true就会告诉Spring我这个方法里面没有insert或者update,你只需要提供只读的数据库Connection就行了,这种 执行效率会比read-write的Connection高,所以这是一个最优化提示 。在一些情况下,一些事务策略能够起到显著的最优化效果,例如在使用Object/Relational映射工具(如:Hibernate或TopLink)时避免dirty checking(试图“刷新”)。 

*timeout  
在属性中还有定义“timeout”值的选项,指定事务超时为几秒。一般不会使用这个属性。在JTA中,这将被简单地传递到J2EE服务器的事务协调程序,并据此得到相应的解释。 

*Isolation Level(事务隔离等级)的5个枚举值  
为什么事务要有Isolation Level这个属性?先回顾下数据库事务的知识: 
第一类丢失更新(lost update) :在完全未隔离事务的情况下,两个事物更新同一条数据资源,某一事物异常终止,回滚造成第一个完成的更新也同时丢失。 
第二类丢失更新(second lost updates) :是不可重复读的特殊情况,如果两个事务都读取同一行,然后两个都进行写操作,并提交,第一个事务所做的改变就会丢失。 
脏读(dirty read) :如果第二个事务查询到第一个事务还未提交的更新数据,形成脏读。因为第一个事务你还不知道是否提交,所以数据不一定是正确的。 
虚读(phantom read) :一个事务执行两次查询,第二次结果集包含第一次中没有或者某些行已被删除,造成两次结果不一致,只是另一个事务在这两次查询中间插入或者删除了数据造成的。 
不可重复读(unrepeated read) :一个事务两次读取同一行数据,结果得到不同状态结果,如中间正好另一个事务更新了该数据,两次结果相异,不可信任。 

具体关于事务机制可以看我以前的博客: http://zhou137520.iteye.com/admin/blogs/1638574  

当遇到以上这些情况时我们可以设置isolation下面这些枚举值: 
DEFAULT :采用数据库默认隔离级别 
SERIALIZABLE :最严格的级别,事务串行执行,资源消耗最大; 
REPEATABLE_READ :保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。 
READ_COMMITTED :大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。 
READ_UNCOMMITTED :保证了读取过程中不会读取到非法数据。隔离级别在于处理多事务的并发问题。 

*关于propagation属性的7个传播行为  
REQUIRED :指定当前方法必需在事务环境中运行,如果当前有事务环境就加入当前正在执行的事务环境,如果当前没有事务,就新建一个事务。这是默认值。 
SUPPORTS :指定当前方法加入当前事务环境,如果当前没有事务,就以非事务方式执行。 
MANDATORY :指定当前方法必须加入当前事务环境,如果当前没有事务,就抛出异常。 
REQUIRES_NEW :指定当前方法总是会为自己发起一个新的事务,如果发现当前方法已运行在一个事务中,则原有事务被挂起,我自己创建一个属于自己的事务,直我自己这个方法commit结束,原先的事务才会恢复执行。 
NOT_SUPPORTED :指定当前方法以非事务方式执行操作,如果当前存在事务,就把当前事务挂起,等我以非事务的状态运行完,再继续原来的事务。 
NEVER :指定当前方法绝对不能在事务范围内执行,如果方法在某个事务范围内执行,容器就抛异常,只有没关联到事务,才正常执行。 
NESTED :指定当前方法执行时,如果已经有一个事务存在,则运行在这个嵌套的事务中.如果当前环境没有运行的事务,就新建一个事务,并与父事务相互独立,这个事务拥有多个可以回滚的保证点。就是指我自己内部事务回滚不会对外部事务造成影响,只对DataSourceTransactionManager事务管理器起效。

***********************************************************************************************

第五种方式:全注解

<? xml version="1.0" encoding="UTF-8" ?>
< beans  xmlns ="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context
="http://www.springframework.org/schema/context"
    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-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
>

    
< context:annotation-config  />
    
< context:component-scan  base-package ="com.bluesky"   />

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

    
< bean  id ="sessionFactory"   
            class
="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >   
        
< property  name ="configLocation"  value ="classpath:hibernate.cfg.xml"   />   
        
< property  name ="configurationClass"  value ="org.hibernate.cfg.AnnotationConfiguration"   />
    
</ bean >   

    
<!--  定义事务管理器(声明式的事务)  -->   
    
< bean  id ="transactionManager"
        class
="org.springframework.orm.hibernate3.HibernateTransactionManager" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >
    
</ beans >

此时在DAO上需加上@Transactional注解,如下:

package  com.bluesky.spring.dao;

import  java.util.List;

import  org.hibernate.SessionFactory;
import  org.springframework.beans.factory.annotation.Autowired;
import  org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import  org.springframework.stereotype.Component;

import  com.bluesky.spring.domain.User;

@Transactional
@Component(
" userDao " )
public   class  UserDaoImpl  extends  HibernateDaoSupport  implements  UserDao {

    
public  List < User >  listUsers() {
        
return   this .getSession().createQuery( " from User " ).list();
    }
    
    
}

    五种配置方式的比较:推荐使用<tx:tags>方式的声明式事务,因为其是无侵入代码的,可以配置模板化的事务属性并运用到多个项目中。 
       而@Transaction注解事务,如果一个项目模块太多,service方法太多导致每个方法都要手动去加注解,是不是很麻烦,也容易出错。如果一个项目结构清晰,分层明确,那么标签形式的配置将是最直观和方便的办法。 
       总之,能保证项目正常工作的事务配置就是最好的。



1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值