spring的嵌套事务控制

来源:互联网 发布:java加密软件 编辑:程序博客网 时间:2024/05/19 23:13

spring的事务控制,嵌套调用时为何不起效

描述: 用spring管理service层事务,然后配置切面,
<tx:advice id="txAdvice" transaction-manager="transactionManager">    <tx:attributes>        <tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Exception" />        <tx:method name="del*" propagation="REQUIRED" rollback-for="java.lang.Exception" />        <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception" />        <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception" />        <tx:method name="do*" propagation="REQUIRED" rollback-for="java.lang.Exception" />        <tx:method name="*" propagation="SUPPORTS" rollback-for="java.lang.Exception" />    </tx:attributes></tx:advice>
 
,满足这三种特征的service方法,能正常实现再异常时回滚。但是,我在service定义了另外一个没有带着个特征的方法,比如searchBrandName(){} 在这个方法里调用"update*"方法,未使用任何try catch,从控制台上看异常被抛出,但是事务却没回滚,请问这是为什么?难道说spring只能看到最终抛出异常的方法,被调用方法是不管的?
 
Spring 的事务传播级别:
PROPAGATION_REQUIRED: 如果存在一个事务, 则支持当前事务. 如果没有事务则开启一个新的事务.<--常用 PROPAGATION_SUPPORTS: 如果存在一个事务, 支持当前事务. 如果没有事务, 则非事务的执行.<--常用 PROPAGATION_MANDATORY: 如果已经存在一个事务, 支持当前事务. 如果没有一个活动的事务, 则抛出异常. PROPAGATION_REQUIRES_NEW: 总是开启一个新的事务. 如果一个事务已经存在, 则将这个存在的事务挂起.<--嵌套事务 PROPAGATION_NOT_SUPPORTED: 总是非事务地执行, 并挂起任何存在的事务 PROPAGATION_NEVER: 总是非事务地执行, 如果存在一个活动事务, 则抛出异常 PROPAGATION_NESTED: 如果一个活动的事务存在, 则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行. 
 
PROPAGATION_REQUIRES_NEW 和PROPAGATION_NESTED的区别主要是:
PROPAGATION_NESTED:这个事务的提交和回滚是依赖于外层事务的是否提交
PROPAGATION_REQUIRES_NEW: 只与自身的事务状态有关, 事务结束即被提交, 不依赖与外部的事务状态.
 
 
 
 
@Overridepublic List<BrandMapping> searchBrandName(String brandName) {    List<BrandMapping> brandMappingList = brandService.findBrand(brandName);    for (int i = 0; i < brandMappingList.size(); i++) {        BrandMapping brandMapping =  brandMappingList.get(i);
// 调用update方法      updateSte(brandMapping, i);    return brandService.findBrand(brandName);}
 
 
public void updateSte(BrandMapping brandMapping, int i) throws Exception{    brandMapping.setBrandName("测试测试...");
// 操作数据库    brandService.updateSte(brandMapping);    if (i == 3){
// 模拟异常出现        i = 1/ 0;    }}
 
以上代码实现发现, updateSte() 方法中并没有事务的, 也就是说这种方式是不支持的,原因是searchBrandName()通过this调用本类的方法,这个方法并不是经过spring代理对象调用,所以AOP的切入是没有的。
 
 
解决办法:自己手动开启事务
@Autowiredprivate DataSourceTransactionManager txManagerGoods;@Overridepublic List<BrandMapping> searchBrandName(String brandName) {    List<BrandMapping> brandMappingList = brandService.findBrand(brandName);    for (int i = 0; i < brandMappingList.size(); i++) {        BrandMapping brandMapping =  brandMappingList.get(i);        DefaultTransactionDefinition def = new DefaultTransactionDefinition();        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);// 事物隔离级别,开启新事务        TransactionStatus status = txManagerGoods.getTransaction(def); // 获得事务状态        try {            updateSte(brandMapping, i);            txManagerGoods.commit(status);        } catch (Exception e) {            // e.printStackTrace();            txManagerGoods.rollback(status);                }    }    return brandService.findBrand(brandName);}public void updateSte(BrandMapping brandMapping, int i) throws Exception{    brandMapping.setBrandName("测试测试...");    brandService.updateSte(brandMapping);    if (i == 3){        i = 1/ 0;    }}
 
 
代码中使用try catch 是因为spring 的事务如果是unchecked的异常的话, 事务都会被回滚的, 所以手动try catch 进行处理.
 
 
 
 
原创粉丝点击