工具类-封装通用编程式事务

前言

大家都知道,spring为我们提供了编程式事务、声明式事务

一、编程式事务

声明式事务是大家使用得比较多的一种方式,这里就不再多说。
主要说下编程式事务,编程式事务的主要目的是减小事务粒度,使回滚数据可以是由开发人员手动控制,代码看起来更清晰些。同时在回滚时可以根据自己需求再处理点业务或记录些信息,当然开发起来也比声明式要多点步骤。
下面写一个简单的编程式事务实例。
1、有返回结果

public void manual() {
        AccountCycleDo accountCycleDo = AccountCycleDo.create();
        //第一次执行新增数据
        dataSourceDao.insertTest(accountCycleDo);
        //第二次执行新增数据,在下面因为唯一键冲突后回滚的只是第二次执行的新增数据
        Integer num = transactionTemplate.execute(transactionStatus -> {
            try {
                //执行业务
                return dataSourceDao.insertTest(accountCycleDo);
            } catch (Exception e) {
                log.error("有返回值,Exception,{}", e);
                //回滚
                transactionStatus.setRollbackOnly();
                return -1;
            }
        });
    }

2、无返回结果

public void manual() {
        AccountCycleDo accountCycleDo = AccountCycleDo.create();
        //第一次执行新增数据
        dataSourceDao.insertTest(accountCycleDo);
        //第二次执行新增数据,在下面因为唯一键冲突后回滚的只是第二次执行的新增数据
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                try {
                    //业务代码
                    dataSourceDao.insertTest(accountCycleDo);
                } catch (Exception e) {
                    log.error("无返回值,Exception,{}", e);
                    //回滚
                    transactionStatus.setRollbackOnly();
                }
            }
        });
    }

都是比较简单的操作,但是如果需要使用的地方多了,每个地方都这样写还是比较麻烦的,所以做了一个简单的封装

二、封装通用工具类

1、编写工具类

package com.dili.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.function.Function;

/**
 * 手动处理事务
 * @author jy
 */
@Component
@Slf4j
public class TransactionalUtil {
    @Resource
    private TransactionTemplate transactionTemplate;

    /**
     * 有返回值
     * @param function
     * @return
     * @param <T>
     */
    public <T> T transactionCallback(Function function){
        Object o = transactionTemplate.execute(transactionStatus -> {
            try {
                //执行业务
                return function.apply(new Object());
            } catch (Exception e) {
                log.error("有返回值,Exception,{}", e);
                //回滚
                transactionStatus.setRollbackOnly();
                return null;
            }
        });
        return (T) o;
    }

    /**
     * 无返回值的
     * @param function
     */
    public void transactionCallbackWithoutResult(Function function){
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                try {
                    //业务代码
                    function.apply(new Object());
                } catch (Exception e) {
                    log.error("无返回值,Exception,{}", e);
                    //回滚
                    transactionStatus.setRollbackOnly();
                }
            }
        });
    }
    public void transactionCallbackWithoutResultOrRollback(Function function1, Runnable function2){
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                try {
                    //业务代码
                    function1.apply(new Object());
                } catch (Exception e) {
                    log.error("无返回值,Exception,{}", e);
                    //回滚
                    transactionStatus.setRollbackOnly();
                    function2.run();
                }
            }
        });
    }
}

2、调用

public void manual() {
        AccountCycleDo accountCycleDo = AccountCycleDo.create();
        //第一次执行新增数据
        dataSourceDao.insertTest(accountCycleDo);
        //第二次执行新增数据,在下面因为唯一键冲突后回滚的只是第二次执行的新增数据
        transactionUtil.transactionCallbackWithoutResult((a)-> dataSourceDao.insertTest(accountCycleDo));
        Integer o = transactionUtil.transactionCallback((a) -> dataSourceDao.insertTest(accountCycleDo));
        log.info("返回结果,{}",o);
        //第三次执行,在回归时可以操作其他的
        transactionUtil.transactionCallbackWithoutResultOrRollback((a)->{
            dataSourceDao.insertTest(accountCycleDo);
            return null;
        },()-> log.info("回滚时,可以做其他的事情,{}",accountCycleDo));
    }

这样抽取后就不用每次都写那么多了,几乎就是只专注业务代码就行了。

总结

简单记录下,丰富自己的工具库吧,大家加油!!!!!!