浑浑噩噩用了spring+(my)ibatis很久,事务的处理基本上都是复制粘贴弄过来,最近需要处理一批数据提交,如果出错都要做回滚,但是spring处理的事务仅仅对出错的那一行(insert/update/delete)进行了回滚,但是以前成功提交的数据都没有回滚。
先使用aop+tx:advice来配置
<aop:aspectj-autoproxy />
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="append*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="modify*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="repair" propagation="REQUIRED" />
<tx:method name="delAndRepair" propagation="REQUIRED" />
<tx:method name="get*" propagation="SUPPORTS" />
<tx:method name="find*" propagation="SUPPORTS" />
<tx:method name="load*" propagation="SUPPORTS" />
<tx:method name="search*" propagation="SUPPORTS" />
<tx:method name="datagrid*" propagation="SUPPORTS" />
<tx:method name="*" propagation="SUPPORTS" />
</tx:attributes>
</tx:advice>
<aop:config proxy-target-class="true">
<aop:advisor pointcut="execution(* com.cssweb.business..*Dao.*(..))" advice-ref="txAdvice"/>
</aop:config>
第一种处理回滚的方式 :在业务代码的catch中捕获到异常使用代码“TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();”、
public void insertTest2() throws Exception{
TestTable1 t = null;
try {
for(int i=0;i<10;i++){
t = new TestTable1("val1-"+i,"val2-"+i,"TEST_A");
this.sqlSessionTemplate.insert(namespace+".insert", t);//制造出一个异常
if(i==6){
throw new Exception("just a test");
}
}
} catch (Exception e) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
第二种方式 抛出运行时异常 RuntimeException。 因为aop默认情况下只会捕获运行时异常,因此可以在catch中抛出RuntimeException,上方“throw new Exception("just a test");”替换成 throw new RuntimeException();
第三种方式 修改tx:method”的属性 rollback-for="java.lang.Exception", 这样在catch中抛出Exception就可以被aop捕获了。
顺便记录一下使用<tx:annotation-driven/> 的简单方法。
spring的配置文件中使用下列代码
<tx:annotation-driven transaction-manager="transactionManager"/>
<aop:aspectj-autoproxy proxy-target-class="true"/>
业务代码如下
@Transactional(propagation=Propagation.REQUIRED, readOnly=false, rollbackFor=Exception.class)
public void insertTest2() throws Exception{
TestTable1 t = null;
try {
for(int i=0;i<10;i++){
t = new TestTable1("val1-"+i,"val2-"+i,"TEST_A");
this.sqlSessionTemplate.insert(namespace+".insert", t);
if(i==6){
throw new Exception("just a test");
}
}
} catch (Exception e) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}