心血来潮分享一下个人对@Transactional 异常的看法及代码片段分享

正文

关于 @Transactional 异常的问题,首先要保证数据源及前置事务配置正确且生效,这是前提,就不在当前结果讨论的范围 (不含多数据源的场景)。

其次spring的@Transactional是通过注解切面实现,这要保证 为spring容器所管理的实例对象且符合切面能正常执行的条件。(方法修饰符应是public

如果当前类是spring的实例类,当前类的方法中直接 this.xxx()进行调用带注解的切面方法,切面功能不会生效。另外 @Transactional 中 propagation 属性可以来指定事务传播行为,一般不指定,使用的是REQUIRED(默认)类型:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。

另外在执行事务的业务逻辑中不能包含耗时计算(如rpc调用、http调用等)

基于业务基本场景一般就涉及带返回值和不带返回值的两种,加上尽量避免 @Transactional 使用的地方过多,可统一放在一处进行维护(避免每次都要特别验证配置是否生效)

以下是博主多年工作推荐的一种实现方式(有需要其他方法或调整自行处理即可,欢迎大家留言交流~):


import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.function.Supplier;

/**
 * @author 新程快咖员
 */
@Service
public class TransactionalTaskHelper {

    private static TransactionalTaskHelper INSTANCE;

    /**
     * 设置实例对象 -- 通过runner、InitializingBean等方式初始化
     *
     * @param instance
     */
    static void setInstance(TransactionalTaskHelper instance) {
        INSTANCE = instance;
    }

    /**
     * 获取实例对象
     *
     * @return
     */
    public static TransactionalTaskHelper getInstance() {
        return INSTANCE;
    }


    /**
     * 不带返回值的业务逻辑执行
     * <p>代码示例:<p>
     * <code>TransactionalTaskHelper.getInstance().execute(() -> {
     * //要执行的业务代码
     * });</code>
     *
     * @param runnable
     */
    @Transactional(rollbackFor = Exception.class)
    public void execute(Runnable runnable) {
        runnable.run();
    }

    /**
     * 带返回值的业务逻辑执行
     * <p>代码示例:<p>
     * <code>TransactionalTaskHelper.getInstance().execute(() -> {
     *             //要执行的业务代码 (这里可以返回任意类型的结果)
     *             return 1;
     *         });</code>
     *
     * @param supplier
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    public <T> T execute(Supplier<T> supplier) {
        return supplier.get();
    }

    @Component
    public static class TransactionalTaskHelperInitializingBean implements InitializingBean {

        @Autowired
        private ApplicationContext applicationContext;

        @Override
        public void afterPropertiesSet() throws Exception {
            setInstance(applicationContext.getBean(TransactionalTaskHelper.class));
        }
    }

}

调用方式:

    //不带返回值的业务逻辑执行
        TransactionalTaskHelper.getInstance().execute(() -> {
            //要执行的业务代码
        });


        //带返回值的业务逻辑执行
        Integer size = TransactionalTaskHelper.getInstance().execute(() -> {
            //要执行的业务代码 (这里可以返回任意类型的结果)
            return 1;
        });

验证事务是否回滚示例: (抛出异常后可见保存的业务1数据被回滚)


     
        TransactionalTaskHelper.getInstance().execute(() -> {
            //要执行的业务代码
            
            //保存业务1数据 todo
            
            if (true) {
                throw new RuntimeException("主动抛出RuntimeException异常测试回滚");
            }


            //保存业务2数据  todo

        });


插件分享

这还是我认识的idea插件吗?搜索maven依赖版本绝了,升级maven版本功能也超级好使~

🎉 结尾

欢迎关注公众号 “新程快咖员” 解锁更多内容!

以上就是本篇文章的全部内容啦,感谢您的阅读和观看。欢迎点赞、转发(分享)和推荐~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值