spring-boot 2.5.3版本
msyql
SpringBoot编程式事务,可以使用2种方式。
Spring模板方式调用TransactionTemplate
默认TransactionAutoConfiguration自动装配。使用时直接注入TransactionTemplate 使用
推荐使用
编写一个测试类,简单测试一下,测试一下异常报错,手动设置回滚状态。
@AutowiredprivateTransactionTemplate transactionTemplate;@TestvoidtemplateTest(){Object execute = transactionTemplate.execute(newTransactionCallback(){/**
* @param transactionStatus 事务运行状态信息 是否是新事务、是否已被标记为回滚等
* @return
*/@OverridepublicObjectdoInTransaction(TransactionStatus transactionStatus){Object result;try{
log.info("执行事务方法");TerminalUserConfig ter =newTerminalUserConfig();
ter.setId(RandomUtil.randomLong());
ter.setConfigKey(RandomUtil.randomString(5));
ter.setConfigValue(RandomUtil.randomString(5));
ter.setUserId(1L);
result = terminalUserConfigMapper.insertTerminalUserConfig(ter);// 手动设置异常int i =1/0;
log.info("正常执行完成");return result;}catch(Exception exception){
log.info("执行事务异常,需要回滚");
transactionStatus.setRollbackOnly();returnfalse;}}});}
控制台打印
简单源码分析
spring提供了TransactionCallback和子类TransactionCallbackWithoutResult。
TransactionCallback默认是带返回值的,子类实现则不带。可以根据实际情况来决定是否需要返回值。
查看TransactionTemplate的execute方法可以知道。默认doInTransaction方法是不需要手动设置回滚状态,只要有异常就会自动回滚。
但是手动设置回滚也是可以,AbstractPlatformTransactionManager会在commit方法中判断事务的状态,然后决定提交还是回滚。
所以至于是否要捕获异常,可以自行决定。既然已经封装了异常捕获回滚,建议还是抛异常即可。
Spring原始方式PlatformTransactionManager
PlatformTransactionManager核心事务管理器 ,用来管理事务,包含事务的提交,回滚。
TransactionDefinition 事务基础信息 超时时间、隔离级别、传播属性等
TransactionStatus 事务状态
@TestvoidmanageTest(){//事务基础信息 超时时间、隔离级别、传播属性等DefaultTransactionDefinition transDef =newDefaultTransactionDefinition();// 定义事务属性// 设置传播行为属性, 默认事务级别。 当前无事务则新建事务,已有事务则加入事务。
transDef.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);// 获得事务状态TransactionStatus status = transactionManager.getTransaction(transDef);try{
log.info("执行事务方法");TerminalUserConfig ter =newTerminalUserConfig();
ter.setId(RandomUtil.randomLong());
ter.setConfigKey(RandomUtil.randomString(5));
ter.setConfigValue(RandomUtil.randomString(5));
ter.setUserId(1L);// 数据库操作
terminalUserConfigMapper.insertTerminalUserConfig(ter);//手动设置异常int i =1/0;
transactionManager.commit(status);// 提交}catch(Exception e){
log.info("执行事务异常,需要回滚");
transactionManager.rollback(status);// 回滚}}
控制台打印
方法需要实施事务管理,我们首先需要在方法开始执行前启动一个事务,调用PlatformTransactionManager.getTransaction(…) 方法便可启动一个事务。创建并启动了事务之后,便可以开始编写业务逻辑代码,然后在适当的地方执行事务的提交或者回滚。
很明显这样原始的方式,事务管理的代码散落在业务逻辑代码中,破坏了原有代码的条理性,并且每一个业务方法都包含了类似的启动事务、提交/回滚事务的模板代码。也可以简单封装成工具类去调用。
所以推荐使用TransactionTemplate
应用场景
在声明式事务流行的当下,编程式事务很少在项目中出现。
编程式事务最大的优点就是灵活可控,缺点就是要手写要规范且麻烦。
- 灵活控制复杂业务流程
- 大事务拆分
声明式事务的最小粒度要作用在方法
一个方法被事务嵌套,那么就可能会在方法中加入一些如RPC远程调用、消息发送、缓存更新、文件写入等操作。
接口会因为处理超长而容易超时,引发调用方事务回滚或者方法内某些业务操作无法自动回滚
大事务的拆分,可以拆分成多个小事务,通过编程式事务来解决。
所以还是要灵活组合使用。不能全部都是声明式事务,可以适当的使用一些编程式事务。当项目中有些奇葩操作出现时,编程式事务就有用武之地了。
版权归原作者 清枫975 所有, 如有侵权,请联系我们删除。