文档详情

spring声明式事务(@Transactional)开发常犯的几个错误及解决办法.docx

发布:2025-05-17约3.12千字共4页下载文档
文本预览下载声明

spring声明式事务(@Transactional)开发常犯的几个错误及解决办法

问题现象:在事务提交后回调事件方法中【即:afterCommit】开启事务不生效(即:添加了@Transactional,也执行了代理方法的调用,但就像没有事务一样,出现报错事务不回滚,也无法在事务方法中再次注册事务提交后回调事务件方法),示例代码如下:

/**代码片段

*@authorzuowenjun

*@see

@Transactional

publicDemoUserdoGetX(){

doInsert(1);

TransactionSynchronizationManager.registerSynchronization(newTransactionSynchronizationAdapter(){

@Override

publicvoidafterCommit(){

selfService.doInsert(2);//走切面调用,确保执行代理的事务方法,但实际还是无事务,报错也不会回滚

returndemoUserMapper.get(1);

@Transactional(propagation=Propagation.REQUIRED)

publicintdoInsert(intid){

DemoUseruser=newDemoUser(id,zs,18,newBigDecimal(8888.88),

shenzhen,cn,newTimestamp(System.currentTimeMillis()),newTimestamp(System.currentTimeMillis()));

intresult=demoUserMapper.insert(user);

if(id==2){

thrownewRuntimeException(mockinsertex

returnresult;

//演示调用:虽然doGetX有报错,但最终doInsert方法均有执行,且都能查出ID=1与2的记录

try{

DemoUserresult=demoUserService.doGetX();

System.out.println(result!=nullresult.toString():none

}catch(Exceptione){

System.out.println(error+e.toString());

DemoUserresult1=demoUserService.get(1);

System.out.println(result1!=nullresult1.toString():none

DemoUserresult2=demoUserService.get(2);

System.out.println(result2!=nullresult2.toString():none

根本原因:在事务提交后回调事件方法中【即:afterCommit】,spring事务的管理状态仍保留(即:仍是事务激活状态)但DB事务其实已提交,当回调方法中又遇到有事务注解的方法时且判断已有事务(即spring事务的管理状态是激活状态transactionActive=true)时,若是默认继承状态则不会再开启新事务,仅复用DB连接

解决方案:在事务提交后回调事件方法中【即:afterCommit】开启新事务(即:传播特性为:REQUIRES_NEW)或者执行前强制清除事务状态【需要编写事务状态清除工具类】,示例代码如下:

/**代码片段

*@authorzuowenjun

*@see

@Transactional

publicDemoUserdoGetX(){

TxManagerUtils.clearTxStatus();//方案二:通过事务状态清除工具类注册事务回调后首先清除事务状态,二选其一即可

doInsert(1);

TransactionSynchronizationManager.registerSynchronization(newTransactionSynchronizationAdapter(){

@Override

publicvoidafterCommit(){

显示全部
相似文档