当前位置: 代码迷 >> J2EE >> spring 事宜 propagation REQUIRES_NEW 未起到新建事务的作用
  详细解决方案

spring 事宜 propagation REQUIRES_NEW 未起到新建事务的作用

热度:609   发布时间:2016-04-17 23:03:25.0
spring 事务 propagation REQUIRES_NEW 未起到新建事务的作用
在此请教一个spring事务的问题
按照如下的配置
Spring中Propagation类的事务属性详解:
PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 
PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。 
PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。 
PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
 PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 
PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。 
PROPAGATION_NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。



TaskServiceHander的batchData()方法中循环多次调用backup_takeTableOldToNew()方法。
backup_takeTableOldToNew()方法中是将A表里的数据的前500条转移到B表中,然后再删除A表的前500条数据。backup_takeTableOldToNew()方法的事务是 propagation="REQUIRES_NEW"。batchData()方法
public void batchData(int begin,int end,int number) throws Exception{
//此处省略部分代码........
        logger.info("Start timing task ...");
        //是否继续执行转存操作
        boolean _is_continue = true;       
        //统计执行次数
        int x =0;
        while(_is_continue){
            //执行操作
            x ++;
            _is_continue = backup_takeTableOldToNew(_old_table, _name_temp_task, _date_before_01, number,begin,end);
        }
        long _end_time = System.currentTimeMillis();
        if(logger.isInfoEnabled()){
            logger.info("共执行备份转换数据"+x+"次,定时任务每次执行任务数:"+number);
            logger.info("End timing task ...,time use : "+(_end_time-_begin_time)/1000+"(secs),msecs:"+(_end_time-_begin_time));
        }
        
    }

而backup_takeTableOldToNew()方法将A表里的数据的前500条转移到B表中,并返回实际执行的条数。
我的想法是在batchData方法调用backup_takeTableOldToNew方法时,让backup_takeTableOldToNew方法每次都能将(A表里的数据的前500条转移到B表中)实际提交到数据库中,但实际操作时,都是batchData执行完之后再提交全部的数据库操作,这样一来。万一batchData方法异常,backup_takeTableOldToNew执行的所有数据库操作全部回滚,在此请教是否哪里配置的有问题???
以下是事务的配置。


 
<aop:config> 
<aop:pointcut id="serviceMethod"
expression="execution(* com.su.*.service.hander.*ServiceHander.*(..))||execution(* com.su.*.service.down.*ServiceDown.*(..))" />
<aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>                            
<tx:method name="backup*" propagation="REQUIRES_NEW" />
<tx:method name="batch*" propagation="REQUIRED" /> 
<tx:method name="write*" propagation="REQUIRED" />
<tx:method name="*" read-only="true" />
</tx:attributes>
</tx:advice>

------解决思路----------------------
while(_is_continue){
            //执行操作
            x ++;
            _is_continue = backup_takeTableOldToNew(_old_table, _name_temp_task, _date_before_01, number,begin,end);
        }
多次循环调用 backup_takeTableOldToNew,多次事物被挂起,无法操作。

建议: backup_takeTableOldToNew不做事物管理,统一在batchData一个事物批处理提交。
------解决思路----------------------
这个方法写到另一个业务类里就可以了
backup_takeTableOldToNew(_old_table, _name_temp_task, _date_before_01, number,begin,end);

执行一次这个方法,就会提交事务。
不管是ebj还是spring,我都遇到这样问题,嵌套的事务里的方法都在一个类里的话,
里面的即时是新建的事务,执行完方法也不会提交。我也没去具体研究什么原因。
但是我是通过这个线程的转换完成的。
  相关解决方案