JAVA Spring + Mybatis如何控制事务在service层

Alfie 发布于 2013/07/22 14:45
阅读 16K+
收藏 1

问题如题,本人使用的是spring tx+aop,配置控制到了services层,配置如下:

<tx:advice id="yqTxAdvice" transaction-manager="transactionManager">
  <tx:attributes>
   <tx:method name="delete*" propagation="REQUIRED" read-only="false"
    rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException" />
   <tx:method name="insert*" propagation="REQUIRED" read-only="false"
    rollback-for="java.lang.Exception" />
   <tx:method name="update*" propagation="REQUIRED" read-only="false"
    rollback-for="java.lang.Exception" />
   <tx:method name="find*" propagation="SUPPORTS" />
   <tx:method name="get*" propagation="SUPPORTS" />
   <tx:method name="select*" propagation="SUPPORTS" />
   <tx:method name="query*" propagation="SUPPORTS" />
  </tx:attributes>
 </tx:advice>

<aop:config>
  <aop:pointcut id="pc"
   expression="execution(* com.yinqing.mosweb.serivices.*.*(..))" /> <!--把事务控制在Service层 -->
  <aop:advisor pointcut-ref="pc" advice-ref="yqTxAdvice" />
 </aop:config>

然后JAVA services中执行如下代码:

@Autowired
 public CellInfoMapper cellInfoMapper;

private static void test() throws Exception{
  throw new Exception();
 }
 
 public boolean insertBatch(List<CellInfoModel> cellInfoModels){
  try{
   Long before = System.currentTimeMillis();
   cellInfoMapper.deleteAll();
   test();
   cellInfoMapper.insertBatch(cellInfoModels);
   Long takeTime = System.currentTimeMillis()-before;
   logger.info("data size :"+cellInfoModels.size()+" take time(millis)"+takeTime);
   return true;
  }catch(Exception e){
   logger.info("批量插入小区信息数据错误!");
   e.printStackTrace();
   return false;
  }
 }

在如上代码中,可以明白,当执行delete方法后,抛出一个异常,然后才执行insertBatch方法,目的是模拟delete方法执行后,后续执行的代码中有异常抛出,此时需要rollback执行了删除的数据。但是发现,如此配置无效,无法将delete的数据rollback回来。

我希望的是一个service方法,不管调用了多少次mapper,都处于同一个事务中,services方法结束,才为一个完整的事务。

 

 

 

加载中
0
黄龍
黄龍
我就知道openSessionInView
Null--Null
Null--Null
这个是mybatis呢,与openSessionInView无关。。。
0
冷血
冷血

你insert*方法中的异常未抛出,spring不知道发生了异常。
未抛出的原因是在catch中使用了return语句,导致异常无法抛出insert*方法之外。
一般是绝对禁止在catch 和finally中使用return语句的。主要是会丢失掉抛出的异常。

冷血
冷血
回复 @Alfie : catch中的return语句去掉没有?异常抛不出去,问题是在这里。
Alfie
Alfie
亲,谢谢回答,首先学习了,spring配置不更改,JAVA方法修改为向上抛出异常,返回值改为void,但问题依旧,仍然无法rollback被deleteAll的数据。
0
Ken5233
Ken5233
spring是靠AOP的方法拦截异常去判断是否需要事务回滚或提交的。你自己把异常给catch了,又不往上抛出 别人怎么知道你的方法是否执行正常呢
Alfie
Alfie
亲,谢谢回答,学习了,现在JAVA方法修改后,是往上抛异常,但是在Action层有做异常处理,这个应该是没问题的。
0
平安北京
应该是service层抛出异常
Alfie
Alfie
现在纠结的情况是,一个mapper方法是一个完整的事务!
0
爪哇小贩
爪哇小贩
你用的springmvc吗?mvc配置文件和app配置文件是分开写的吗?
Alfie
Alfie
不是用的springmvc,谢谢
0
杨金昌1
杨金昌1
版本不对,我试过只有spring和mybatis都用3.0.6版本才支持申明式事务,楼主可以换版本试一下。
Alfie
Alfie
spring 用的是3.1.1版本,mybatis 3.1.0版本
0
l
lihx
catch 里不  return false; 直接 throw new Exception()
0
xx_ton
xx_ton
<tx:method name="delete*" propagation="REQUIRED" read-only="false"

    rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException" />

它抛出的正是RuntimeException

返回顶部
顶部