在此请教一个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>事务SpringJava调用

解决方案 »

  1.   

    while(_is_continue){
                //执行操作
                x ++;
                _is_continue = backup_takeTableOldToNew(_old_table, _name_temp_task, _date_before_01, number,begin,end);
            }
    多次循环调用 backup_takeTableOldToNew,多次事物被挂起,无法操作。建议: backup_takeTableOldToNew不做事物管理,统一在batchData一个事物批处理提交。
      

  2.   

    但是这里的backup_takeTableOldToNew会被循环N次,N的大小受A的记录数影响,每次insert A from B的500行,(目的是定期将A的数据转移到B这张备份表中),但如果交由batchData一个事务提交 ,会抛出异常。因为统一一起提交的记录数会很大,预计会有200万条。
    求解,有什么其他好的办法来转移A这张表里的数据。数据库:DB2。
      

  3.   

    这个方法写到另一个业务类里就可以了
    backup_takeTableOldToNew(_old_table, _name_temp_task, _date_before_01, number,begin,end);执行一次这个方法,就会提交事务。
    不管是ebj还是spring,我都遇到这样问题,嵌套的事务里的方法都在一个类里的话,
    里面的即时是新建的事务,执行完方法也不会提交。我也没去具体研究什么原因。
    但是我是通过这个线程的转换完成的。
      

  4.   

    我也遇到这样的问题 , 同一个业务类里面 , 即使声明为 Propagation.REQUIRES_NEW也不会新启一个事务。
    必须调用另一个类的Propagation.REQUIRES_NEW方法才行, 这个问题很困惑,至今也不知道是什么原因。