spring的嵌套事务控制

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: 只与自身的事务状态有关, 事务结束即被提交, 不依赖与外部的事务状态.
 
 
 
 
@Override
public 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的切入是没有的。
 
 
解决办法:自己手动开启事务
@Autowired
private DataSourceTransactionManager txManagerGoods;
@Override
public 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 进行处理.
 
 
 
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值