无事务运行代码原创
金蝶云社区-lzpeng723
lzpeng723
3人赞赏了该文章 1,214次浏览 未经作者许可,禁止转载编辑于2022年05月14日 11:21:15

 事务相关知识请查看 事务的四种隔离级别和七种传播机制


有时需要在操作插件(AbstractOperationServicePlugIn)的beginOperationTransaction和endOperationTransaction方法中执行一些事务外的逻辑,比如主操作没有执行成功,但是需要向将日志等信息存入数据库中,此时可以使用以下工具类实现无事务运行代码。



import kd.bos.db.tx.TX;
import kd.bos.db.tx.TXHandle;
import kd.bos.exception.ErrorCode;
import kd.bos.exception.KDException;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;

import java.util.function.*;

/**
 * 事务相关工具类
 *
 * @author lzpeng
 * @version 1.0
 * @date 2022/1/4 12:15
 */
public final class TxUtils {

    private static final Log log = LogFactory.getLog(TxUtils.class);

    /**
     * 无事务运行
     *
     * @param runnable runnable
     * @return 执行结果
     */
    public static void executeNoTx(Runnable runnable) {
        executeNoTx((Consumer<TXHandle>) txHandle -> runnable.run());
    }

    /**
     * 无事务运行
     *
     * @param supplier Supplier
     * @param <T>
     * @return 执行结果
     */
    public static <T> T executeNoTx(Supplier<T> supplier) {
        return executeNoTx((Function<TXHandle, ? extends T>) notTx -> supplier.get());
    }

    /**
     * 无事务运行
     *
     * @param consumer
     */
    public static void executeNoTx(Consumer<TXHandle> consumer) {
        executeNoTx((BiConsumer<TXHandle, TXHandle>) (txHandle, notTx) -> consumer.accept(notTx));
    }

    /**
     * 无事务运行
     *
     * @param biConsumer
     */
    public static void executeNoTx(BiConsumer<TXHandle, TXHandle> biConsumer) {
        executeNoTx((BiFunction<TXHandle, TXHandle, Void>) (txHandle, notTx) -> {
            biConsumer.accept(txHandle, notTx);
            return null;
        });
    }

    /**
     * 无事务运行
     *
     * @param function
     * @param <T>
     * @return 执行结果
     */
    public static <T> T executeNoTx(Function<TXHandle, T> function) {
        return executeNoTx((BiFunction<TXHandle, TXHandle, ? extends T>) (txHandle, notTx) -> function.apply(notTx));
    }

    /**
     * 无事务运行
     *
     * @param biFunction
     * @param <T>
     * @return 执行结果
     */
    public static <T> T executeNoTx(BiFunction<TXHandle, TXHandle, T> biFunction) {
        return executeWithTX(txHandle -> {
            try (TXHandle notTx = TX.notSupported()) {
                return biFunction.apply(txHandle, notTx);
            }
        });
    }

    /**
     * 有事务运行
     *
     * @param runnable runnable
     * @return 执行结果
     */
    public static void executeWithTX(Runnable runnable) {
        executeWithTX((Consumer<TXHandle>) txHandle -> runnable.run());
    }

    /**
     * 有事务运行
     *
     * @param supplier
     * @param <T>
     * @return 执行结果
     */
    public static <T> T executeWithTX(Supplier<T> supplier) {
        return executeWithTX((Function<TXHandle, ? extends T>) txHandle -> supplier.get());
    }


    /**
     * 有事务运行
     *
     * @param consumer
     */
    public static void executeWithTX(Consumer<TXHandle> consumer) {
        executeWithTX((Function<TXHandle, Void>) txHandle -> {
            consumer.accept(txHandle);
            return null;
        });
    }

    /**
     * 有事务运行
     *
     * @param function
     * @param <T>
     * @return 执行结果
     */
    public static <T> T executeWithTX(Function<TXHandle, T> function) {
        try (TXHandle txHandle = TX.requiresNew()) {
            try {
                return function.apply(txHandle);
            } catch (Exception e) {
                txHandle.markRollback();
                throw wrapKDException(e);
            }
        }
    }

    /**
     * 包装为 KDException
     *
     * @param e 异常
     * @return
     */
    private static KDException wrapKDException(Throwable e) {
        log.error(e);
        if (e instanceof KDException) {
            return (KDException) e;
        }
        return new KDException(e, new ErrorCode("TXException", e.getMessage()));
    }

    /**
     * 抛出 KDException
     *
     * @param e 异常
     * @return
     */
    private static KDException throwKDException(Throwable e) {
        throw wrapKDException(e);
    }

}


使用方式

import org.junit.Test;

/**
 * @author lzpeng
 * @version 1.0
 * @date 2022/5/14 10:34
 */
public class TxUtilsTest {

    /**
     * 测试无事务运行
     */
    @Test
    public void testExecuteNoTx() {
        TxUtils.executeNoTx(() -> {});
        TxUtils.executeNoTx(() -> null);
        TxUtils.executeNoTx(tx -> {});
        TxUtils.executeNoTx(tx -> tx);
        TxUtils.executeNoTx((tx1,tx2) -> {});
        TxUtils.executeNoTx((tx1,tx2) -> null);
    }

    /**
     * 测试有事务运行
     */
    @Test
    public void testExecuteWithTX() {
        TxUtils.executeWithTX(() -> {});
        TxUtils.executeWithTX(() -> null);
        TxUtils.executeWithTX(tx -> {});
        TxUtils.executeWithTX(tx -> tx);
    }

}


赞 3