@Transactional,自己抛出异常时不会回滚

今天,面试的时候,突然被问到了一个点,结果,这个自己踩的坑,自己都忘记了。

前年,接手了一个项目,一直会有并发的情况,导致插入重复数据的情况。所以在项目中使用了事务 + 数据库锁,来处理并发。

伪代码如下:

    @Transactional
    public <T> T lock(Staff staff, Trade trade, ILockCallback<T> lockCallback) {
    
        T result;
        long start = System.currentTimeMillis();
        try {
            //先插入数据库锁
            dao.batchInsert(staff, trade);
            //对订单的业务操作
            result = lockCallback.callback();
            //提交,释放锁
        } catch (Exception e) {
            //回滚,释放锁
            logger.error("处理出错, 记录相关的出错日志");
            throw new LockException(e.getMessage());
        } finally {
            if (logger.isDebugEnabled()){
                logger.debug("执行结束, 记录相关耗时"");
            }
        }
        return result;
    }

如果,处理业务逻辑出错了,怎么办,当然是事务回滚了。 然后大佬问了句,出现了这个异常,但是不能触发回滚怎么办,我的第一反应,放在了后面定时清理数据库中相关锁记录的数据上。

事后想想,才get到点,“出现了异常,不能触发回滚”,这个就是当时我踩到的坑,Spring的AOP即声明式事务管理默认是针对unchecked exception回滚。所以catch住粗粒度异常(项目汇总不要catch粗异常),抛异常这里要自己封装下异常,这个异常是要继承runtimeexception, error类和runtimeexception及其子类是unchecked exception,至于什么是unchecked exception,什么是checked exception 可以看我之前的总结。

嘛耶,搞这么久,居然这么坑点,自己忘记了。。。。

基于Spring的AOP即声明式事务管理默认是针对unchecked exception回滚这个原理,可以有很多套路的来处理业务的。

这也是,正常我们写一个项目中,最最基本的简单处理方式了。

猜你喜欢

转载自blog.csdn.net/u010372981/article/details/81291783