使用lambda表达式优雅你的事务代码

我们在实现业务逻辑时,经常会有这种需求:

1、在当前事务A中开启新事务B,事务B中发生异常不可以回滚A,事务B成功执行后返回事务B的返回值;

2、在当前事务A中开启新事务B,事务B中发生异常要求回滚A,事务B成功执行后返回事务B的返回值;

3、在当前事务A中开启新事务B,事务B中发生异常不可以回滚A,事务B成功执行后不需要返回;

4、在当前事务A中开启新事务B,事务B中发生异常要求回滚A,事务B成功执行后不需要返回;

5、注册后置事务B,即当前事务A成功提交后才会执行事务B,事务B异常的话不抛出,只打印异常日志;

6、注册后置事务B,即当前事务A异常时执行事务B,事务B异常的话不抛出,只打印异常日志;

 


一、配置事务模版

<!--事务模版
    1.标志REQUIRES_NEW会新开启事务,外层事务异常外部事务会会馆,不会回滚内部事务的提交
    2.标志REQUIRES_NEW的内部事务的异常,内部事务会回滚,外部事务也会回滚-->
    <bean id="transactionTemplateNew" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager">
            <ref bean="transactionManager"/>
        </property>
        <property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW"/>
    </bean>

 

二、定义接口

/**
 * @author zhaojiatao
 * @date 2019-07-14
 */
public interface ICommonTransactionService {

    /**
     * 开启一个新事务来执行函数,有返回值;与外部事务互相隔离,发生异常只回滚本事务,不会互相影响
     * @param action
     * @param <T>
     * @urn
     */
    <T> T newTransactionExecuteAndReturnWithOutThrowable(Supplier<T> action);

    /**
     * 开启一个新事务来执行函数,有返回值;内部事务发生异常时会向外抛出异常,内部事务和外部事务均回滚
     * @param action
     * @param <T>
     * @urn
     */
    <T> T newTransactionExecuteAndReturnThrowable(Supplier<T> action) throws Exception;

    /**
     * 开启一个新事务来执行函数,无返回值;与外部事务互相隔离,发生异常只回滚本事务,不会互相影响
     * @param f
     */
    void newTransactionRunVoidWithOutThrowable(Runnable f);

    /**
     * 开启一个新事务来执行函数,无返回值;内部事务发生异常时会向外抛出异常,内部事务和外部事务均回滚
     * @param f
     */
    void newTransactionRunVoidThrowable(Runnable f) throws Exception;



    /**
     * 如果当前存在事务,则等当前事务提交后,回头来开启一个新事务执行,如果内部捕捉异常,不往外抛出;如果外部事务提交前外部事物异常,则此函数不会被执行
     * https://docs.spring.io/spring/docs/1.2.7/javadoc-api/org/springframework/transaction/support/TransactionSynchronizationAdapter.html
     * @param f
     */
    void registerTransactionAfterCommitNoThrowable(Runnable f);

    /**
     * 当前事务提交或者回滚后执行 Invoked after transaction commit/rollback
     * https://docs.spring.io/spring/docs/1.2.7/javadoc-api/org/springframework/transaction/support/TransactionSynchronizationAdapter.html
     * @param f
     */
    void registerTransactionAfterRollBackNoThrowable(Runnable f);



}

 

 

三、接口实现

/**
 * @author zhaojiatao
 * @date 2019-07-14
 */

@Slf4j
@Service("commonTransactionService")
public class CommonTransactionServiceImpl  implements ICommonTransactionService {

    @Autowired
    @Qualifier("transactionTemplateNew")
    TransactionTemplate transactionTemplateNew;

    @Override
    public <T> T newTransactionExecuteAndReturnWithOutThrowable(Supplier<T> action) {
        //执行带有返回值<Object>的事务管理
        return transactionTemplateNew.execute(transactionStatus-> {
                    try {
                        return action.get();
                    } catch (Exception e) {
                        log.error("newTransactionExecuteAndReturnNoThrowable发生异常",e);
                        //回滚
                        transactionStatus.setRollbackOnly();
                        return null;
                    }
                });
    }

    @Override
    public <T> T newTransactionExecuteAndReturnThrowable(Supplier<T> action) {
        //执行带有返回值<Object>的事务管理
        return transactionTemplateNew.execute(transactionStatus-> {
            try {
                return action.get();
            } catch (Exception e) {
                log.error("newTransactionExecuteAndReturnNoThrowable发生异常",e);
                //回滚
                transactionStatus.setRollbackOnly();
                throw e;
            }
        });
    }

    @Override
    public void newTransactionRunVoidWithOutThrowable(Runnable f) {
        //执行无返回值的事务管理
        transactionTemplateNew.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                try {
                    //业务代码
                    f.run();
                } catch (Exception e){
                    log.error("newTransactionRunVoidNoThrowable发生异常",e);
                    //回滚
                    transactionStatus.setRollbackOnly();
                }

            }
        });


    }


    @Override
    public void newTransactionRunVoidThrowable(Runnable f) {
        //执行无返回值的事务管理
        transactionTemplateNew.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                try {
                    //业务代码
                    f.run();
                } catch (Exception e){
                    log.error("newTransactionRunVoidNoThrowable发生异常",e);
                    //回滚
                    transactionStatus.setRollbackOnly();
                    throw e;
                }

            }
        });


    }


    @Override
    public void registerTransactionAfterCommitNoThrowable(Runnable f) {
        try{
            if (TransactionSynchronizationManager.isActualTransactionActive()) {
                TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                    @Override
                    public void afterCommit() {
                        f.run();
                    }
                });
            } else {
                f.run();
            }
        }catch (Exception e){
            log.error("执行后置事务发生异常",e);
        }

    }

    @Override
    public void registerTransactionAfterRollBackNoThrowable(Runnable f) {
        try{
            if (TransactionSynchronizationManager.isActualTransactionActive()) {
                TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                    @Override
                    public void afterCompletion(int status) {
                        log.error("执行事务回滚后置事务,status={}",status);
                        f.run();
                    }
                });
            } else {
                f.run();
            }
        }catch (Exception e){
            log.error("当前事务回滚后置事务发生异常",e);
        }
    }

}

 

 

 

四、调用

@Test
    @Transactional(rollbackFor = Exception.class)
    public void commonTransactionServiceTest() throws Exception {

        //1、newTransactionExecute 开启新事务 有返回值
        String result=commonTransactionService.newTransactionExecuteAndReturnWithOutThrowable(
                ()->{
                    QueryObj queryObj = new QueryObj();
                    queryObj.setQuerydo(new OrderDO());
                    queryObj.addQueryParam(new QueryParam("id = #{id}", "347"));
                    OrderDO orderDO = orderDAO.querySingle(queryObj);
                    return JSON.toJSONString(orderDO);
                }
        );

        log.info(result);

        //2、newTransactionRun 开启新事务 无返回值
        commonTransactionService.newTransactionRunVoidWithOutThrowable(
                ()->{
                    QueryObj queryObj = new QueryObj();
                    queryObj.setQuerydo(new OrderDO());
                    queryObj.addQueryParam(new QueryParam("id = #{id}", "347"));
                    OrderDO orderDO = orderDAO.querySingle(queryObj);
                    log.info(JSON.toJSONString(orderDO));
                }
        );

        int[] ids=new int[]{0};

        //3、在新事务中insert数据
        commonTransactionService.newTransactionRunVoidWithOutThrowable(
                ()->{
                    OrderDO orderDO=new OrderDO();
                    orderDO.setId(350L);
                    orderDO.setOrderCode("350350");
                    orderDO.setCustomerId(81L);
                    orderDO.setBusinessModel(LoanOrderBusinessModelEnum.SELF_SECOND_CAR_ICBC_DIRECT.getCode());
                    ids[0]=orderDAO.create(orderDO);
                    log.info( ids[0]+"");
                    //只回滚内部事务,不回滚外部事务
                    System.out.println(1/0);
                }
        );

        //4、在外部事务提交后执行的后置新事务insert数据
        commonTransactionService.registerTransactionAfterCommitNoThrowable(
                ()->{
                    OrderDO orderDO=new OrderDO();
                    orderDO.setId(351L);
                    orderDO.setOrderCode("351351");
                    orderDO.setCustomerId(81L);
                    orderDO.setBusinessModel(LoanOrderBusinessModelEnum.SELF_SECOND_CAR_ICBC_DIRECT.getCode());
                    ids[0]=orderDAO.create(orderDO);
                    log.info( ids[0]+"");
                }

        );

        //5、在外部事务中insert数据
        if(true){
            OrderDO orderDO=new OrderDO();
            orderDO.setId(352L);
            orderDO.setOrderCode("352352");
            orderDO.setCustomerId(81L);
            orderDO.setBusinessModel(LoanOrderBusinessModelEnum.SELF_SECOND_CAR_ICBC_DIRECT.getCode());
            ids[0]=orderDAO.create(orderDO);
            log.info( ids[0]+"");
        }

        //6、在新事务中插入数据并异常
        commonTransactionService.newTransactionRunVoidThrowable(
                ()->{
                    OrderDO orderDO=new OrderDO();
                    orderDO.setId(353L);
                    orderDO.setOrderCode("353353");
                    orderDO.setCustomerId(81L);
                    orderDO.setBusinessModel(LoanOrderBusinessModelEnum.SELF_SECOND_CAR_ICBC_DIRECT.getCode());
                    ids[0]=orderDAO.create(orderDO);
                    log.info( ids[0]+"");
                    System.out.println(1/0);
                }
        );



        //注意验证这个异常是无法回滚commonTransactionService.newTransactionRun的
        //注意验证这个异常会导致commonTransactionService.registerTransactionAfterCommitNoThrowable无法执行,因为事务没有提交
//        System.out.println(1/0);
        System.out.println(1);



    }

 

posted on 2019-07-24 15:40  zhaojiatao  阅读(1795)  评论(0编辑  收藏  举报

导航