spring 事务总结

以往我们需要事务控制的时候,通常需要引入笨重的EJBSpring的出现改变了这种状况,我们可以用Spring的轻量级容器来管理事务。Spring对事务的控制有几种方式:

1.编码的方式

 

class   CourseServiceImpl
{
    
public void enrollStudentInCourse()
    
{
        transactionTemplate.execute(
            
new TransactionCallback()
        
{
            
public Object doInTransaction(TransactionStatus ts)
            
{
                    
try{
                        
// do staff
                    }
catch(Exception e){
                        ts.setRollbackOnly();
                    }

                    
return null;//如果成功,事务被提交
            }

        }

            );
    }

}

 

transactionTemplate实例是从那里来的呢?他将被注入到CourseServiceImpl,代码如下:

< bean  id ="transactionTemplate"  class ="" org.springframework.transaction.support.TransactionTemplate" >
    
< property  name ="transactionManager" >
        
< ref  bean ="transactionManager" />
    
</ property >
</ bean >
< bean  id ="courseService"  class ="com.springinaction.training.service.CourseServiceImpl" >
    
< property  name ="transactionTemplate" >
        
< ref  bean ="transactionTemplate" />
    
</ property >
</ bean >

 

通常,你的事务的需求并没有要求在事务的边界上进行如此精确的控制,这就是我们一般选择在应用代码之外声明事务的原因。

2.声名的方式

Spring里,事务属性是对事务策略如何应用到方法的描述,这个描述包括下列一个或多个参数:

l        传播行为

l        隔离级别

l        只读提示

l        事务超时间隔

事务的传播行为主要包含以下几个:

Ø        PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

Ø         PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。

Ø        PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。

Ø        PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。

Ø        PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

Ø        PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。

     关于事务的传播行为,具体可以参照http://fhjxp.javaeye.com/blog/124978,写的比较详细。

     关于事务的隔离级别:

Isolation Level(事务隔离等级):
1
Serializable:最严格的级别,事务串行执行,资源消耗最大;

2REPEATABLE READ:保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了脏读取不可重复读取的情况,但是带来了更多的性能损失。

3READ COMMITTED:大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了脏读取。该级别适用于大多数系统。

4Read Uncommitted:保证了读取过程中不会读取到非法数据。

隔离级别在于处理多事务的并发问题。
我们知道并行可以提高数据库的吞吐量和效率,但是并不是所有的并发事务都可以并发运行,这需要查看数据库教材的可串行化条件判断了。
这里就不阐述。
我们首先说并发中可能发生的3中不讨人喜欢的事情
1
   Dirty reads--读脏数据。也就是说,比如事务A的未提交(还依然缓存)的数据被事务B读走,如果事务A失败回滚,会导致事务B所读取的的数据是错误的。

2   non-repeatable reads--数据不可重复读。比如事务A中两处读取数据-total-的值。在第一读的时候,total100,然后事务B就把total的数据改成200,事务A再读一次,结果就发现,total竟然就变成200了,造成事务A数据混乱。

3   phantom reads--幻象读数据,这个和non-repeatable reads相似,也是同一个事务中多次读不一致的问题。但是non-repeatable reads的不一致是因为他所要取的数据集被改变了(比如total的数据),但是phantom reads所要读的数据的不一致却不是他所要读的数据集改变,而是他的条件数据集改变。比如Select account.id where account.name="ppgogo*",第一次读去了6个符合条件的id,第二次读取的时候,由于事务b把一个帐号的名字由"dd"改成"ppgogo1",结果取出来了7个数据。

Dirty reads          non-repeatable reads            phantom reads
Serializable                    
不会                   不会                           不会

REPEATABLE READ          
不会                   不会                           
READ COMMITTED           
不会                                                
Read Uncommitted           
                                                 

readOnly

事务属性中的readOnly标志表示对应的事务应该被最优化为只读事务。这是一个最优化提示。在一些情况下,一些事务策略能够起到显著的最优化效果,例如在使用Object/Relational映射工具(如:HibernateTopLink)时避免dirty checking(试图刷新)。

Timeout

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

 

以上所阐述的为基础部分,下面我们看看Spring声明事务的策略有那几种!

l        TransactionProxyFactoryBean参照一个方法的事务属性,决定如何在那个方法上执行事务策略,但是TransactionProxyFactoryBean从哪里得到一个方法的事务特性呢?TransactionProxyFactoryBean有一个transactionAttributeSource属性,这个属性被设置成一个transactionAttributeSource的实例,transactionAttributeSource是作为在方法上查找事务属性的一个参考。


< bean  id ="transactionAttributeSource"  class ="org.springframework.transaction.inteceptor.MatchAlwaysTransactionAttributeSource" >
</ bean >

 

MatchAlwaysTransactionAttributeSource可能是最简单的TransactionAttributeSource的实现,它每一次调用它的getTransactionAttribute()方法被调用过,它总是简单的返回相同的TransactionAttribtue,而不管这个事务包含了什么方法(PROPAGATION_REQUIREDISOLATION_DEFAULT)。那就是MatchAlwaysTransactionAttributeSource永远匹配在起作用;同时你也可以改变默认的事务属性:


< bean  id ="myTransactionAttribute"  class ="org.springframework.transaction.interceptor.DefaultTransactionAttribute" >
    
< property  name ="propagationBehaviorName" >
        
< value > PROPAGATION_REQUIRED_NEW </ value >
    
</ property >
    
< property  name ="isolationLevelName" >
        
< value > ISOLATION_REPEATABLE_READ </ value >
    
</ property >
</ bean >
< bean  id ="transactionAttributeSource"  class ="org.springframework.transaction.inteceptor.MatchAlwaysTransactionAttributeSource" >
    
< property  name ="transactionAttribute" >
        
< ref  bean ="myTransactionAttribute" />
    
</ property >
</ bean >

 

l        通过方法名声名事务

类似与EJB中的CMT,也就是CMT等价物。


< bean  id ="transactionAttributeSource"  class ="org.springframework.transaction.inteceptor.NameMatchTransactionAttributeSource" >
    
< properties  name ="properties" >
        
< props >
            
< prop  key ="get*" >
                PROPAGATION_REQUIRED_NEW
            
</ prop >
        
</ props >
    
</ properties >
</ bean >

 

3.        用元数据声明事务(少用)

 实际在项目中用到的配置为:

 

    < bean  id ="transactionInterceptor"
        class
="org.springframework.transaction.interceptor.TransactionInterceptor" >
        
< property  name ="transactionManager"  ref ="transactionManager" />
            
< property  name ="transactionAttributes" >
                
< props >
                    
< prop  key ="save*" > PROPAGATION_REQUIRED,-JbssAppException </ prop >
                    
< prop  key ="remove*" > PROPAGATION_REQUIRED,-JbssAppException </ prop >
                    
< prop  key ="update*" > PROPAGATION_REQUIRED,-JbssAppException </ prop >
                    
< prop  key ="create*" > PROPAGATION_REQUIRED,-JbssAppException </ prop >
                    
< prop  key ="delete*" > PROPAGATION_REQUIRED,-JbssAppException </ prop >
                    
< prop  key ="add*" > PROPAGATION_REQUIRED,-JbssAppException </ prop >
                    
< prop  key ="get*" > PROPAGATION_REQUIRED,readOnly,-JbssAppException </ prop >
                    
< prop  key ="find*" > PROPAGATION_REQUIRED,readOnly,-JbssAppException </ prop >
                
</ props >
            
</ property >
    
</ bean >
    
< bean  id ="manager"  parent ="txProxyTemplate" >
       
< property  name ="target" >
           
< bean  class ="com.jbss.service.base.impl.BaseManagerImpl" >
                
< property  name ="dao"  ref ="dao"   />
           
</ bean >
       
</ property >
    
</ bean >
    
< bean  id ="log"  class ="com.jbss.util.LogAdvice" />
    
< bean  id ="txProxyTemplate"  class ="org.springframework.aop.framework.ProxyFactoryBean" >  
        
< property  name ="interceptorNames" >
            
< list >
                
< value > log </ value >
                
< value > transactionInterceptor </ value >
            
</ list >
        
</ property >
    
</ bean >
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值