我们在实现业务逻辑时,经常会有这种需求:
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); }