spring中事务的在循环中的内层事务使用

一、业务需求:一个循环,循环中会调用数据库,而且还有业务处理逻辑,现在要求循环中的异常不能中断循环的执行

二、解决:可以将循环体中的内容单独提出写成一个方法,并在上面加上@Transactional(rollbackFor = Exception.class)

这种解决有问题,经过测试,此时的事务是不起作用的,数据依然会被插入(或修改)

三、进一步解决:spring中的事务管理使用到了代理模式,方法直接调用内部方法是不会走到代理类的,也就是不会走到切面,所以@Transactional可能会失效,所以直接调用相当于this.调用内层方法时是不生效的,因此要通过代理对象的方式调用内层方法,

获取代理对象的方法:

Object proxy = AopContext.currentProxy();
//使用时强转为方法所在类
ServiceImpl proxy = (ServiceImpl)AopContext.currentProxy(); Serviceimpl为方法所在类

注意:

要在方法所在类(也就是要获取的代理对象的类上加上下面注解),否则会出现异常信息:

Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.

@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)

也可以通过配置xml

<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>

这样就可以使事务生效,如果外层的方法也要加上事务,需要在内层的事务上加上propagation=Propagation.NESTED属性,让内层事务不会影响到外层事务。

~~~~~~~~~~~~~~~~~~~~~~~~~~以下为测试代码~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

@Service
@EnableAspectJAutoProxy(proxyTargetClass = true,exposeProxy = true)//注意项
public class HistoryStockServiceImpl extends BaseService implements HistoryStockService {

...

@Override
public void test() {
    HistoryStockServiceImpl service = (HistoryStockServiceImpl)AopContext.currentProxy();
    for (int i = 0; i < 10; i++) {
        try {
            service.upda(i);
            System.out.println("~~~~~~~~~~~i:"+i);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        System.out.println("~~~~~~~~~~~~~~循环次数:"+i);
    }
    System.out.println("~~~~~~~~~~~~~运行结束");
}
@Transactional(propagation = Propagation.NESTED,rollbackFor = Exception.class)
public void upda(int a){
    historyStockMapper.upda();
    if(a==5){
        int i=1/0;
    }
}

dao层为普通的修改数据库加1操作,此处不粘图

结果:除第5此异常外,其他日志正常数据,数据库由0增加到了9

方法2:可以将循环内层的需要事务的方法写到其他的处理类中,在此类中引入那个类也可以使事务生效

百度参考:https://www.cnblogs.com/qsbnj/p/14389703.htmlhttps://www.cnblogs.com/yanggb/p/13227072.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值