在此请教一个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,我都遇到这样问题,嵌套的事务里的方法都在一个类里的话,
里面的即时是新建的事务,执行完方法也不会提交。我也没去具体研究什么原因。
但是我是通过这个线程的转换完成的。