日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

记一次事务报错问题 Transaction synchronization is not active

發布時間:2025/4/16 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 记一次事务报错问题 Transaction synchronization is not active 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題場景

在一次請求的返回結果中出現了這個錯誤信息“Transaction synchronization is not active”,意思是“事務同步器沒有激活”,看著不像是業務代碼里返回的提示,猜測是spring事務框架報出來的異常沒有被捕獲而報的錯,在代碼里一通搜索之后確實沒發現這個提示信息,那是什么原因引起了這個異常呢?Google之。

出現原因

Google一番之后,發現了這篇文章Spring的TransactionEventListener,文中提到了可能出現這個錯誤信息的一種情況:

@EventListener public void afterRegisterSendMail(MessageEvent event) {// Spring 4.2 之前TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {@Overridepublic void afterCommit() {internalSendMailNotification(event);}}); }

上面的代碼將在事務提交后執行.如果在非事務context中將拋出java.lang.IllegalStateException: Transaction synchronization is not active

于是去代碼中搜索TransactionSynchronizationManager,果然在當前請求鏈路中的一個service里發現了類似的代碼:

TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {@Overridepublic void afterCommit() {logger.info("afterCommit_car_move_to_otherwarehouse_carIds:{}", new Gson().toJson(form.getCarIdList()));for (Long wmsCarId : form.getCarIdList()) {MovedCarMessage movedCarMessage = new MovedCarMessage();movedCarMessage.setOldCarId(wmsCarId);Message message = MessageBuilder.of(movedCarMessage).topic(carMoveToOtherWarehouseMessageTopic).build();messageProducer.syncSend(message);}}});

想必是執行這段代碼的時候報的異常,但是上面那篇文章說了引起這個異常的原因是“在非事務context中注冊同步器”,難道當前事務沒有開啟?我們的業務代碼一般都是使用spring的注解@Transactional來開啟事務,那么去看一下開啟事務的代碼片段。

根本原因

我在調用TransactionSynchronizationManager.registerSynchronization()的方法體上找到了@Transactional注解,方法代碼如下,省略具體實現:

@Transactional@Overridepublic BizResult departingCar(CarDepartingForm form, User user) {···}

這就奇怪了,明明方法上已經添加@Transactional注解開啟事務,為什么事務開啟失敗,帶著這個疑問再次求助了Google,發現了這篇博客spring的service類調用自己方法事務無效,作者也遇到了事務無效的問題,其中總結了事務有效性相關的幾點重要信息:

1.在需要事務管理的地方加@Transactional 注解。@Transactional 注解可以被應用于接口定義和接口方法、類定義和類的 public 方法上。

2.@Transactional 注解只能應用到 public 可見度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不會報錯, 但是這個被注解的方法將不會展示已配置的事務設置。

3.注意僅僅 @Transactional 注解的出現不足于開啟事務行為,它僅僅 是一種元數據。必須在配置文件中使用配置元素,才真正開啟了事務行為。(spring配置文件中,開啟聲明式事務)

4.通過 元素的 “proxy-target-class” 屬性值來控制是基于接口的還是基于類的代理被創建。如果 “proxy-target-class” 屬值被設置為 “true”,那么基于類的代理將起作用(這時需要CGLIB庫cglib.jar在CLASSPATH中)。如果 “proxy-target-class” 屬值被設置為 “false” 或者這個屬性被省略,那么標準的JDK基于接口的代理將起作用。

5.Spring團隊建議在具體的類(或類的方法)上使用 @Transactional 注解,而不要使用在類所要實現的任何接口上。在接口上使用 @Transactional 注解,只能當你設置了基于接口的代理時它才生效。因為注解是 不能繼承 的,這就意味著如果正在使用基于類的代理時,那么事務的設置將不能被基于類的代理所識別,而且對象也將不會被事務代理所包裝。

6.@Transactional的事務開啟 ,或者是基于接口的 或者是基于類的代理被創建。所以在同一個類中一個無事務的方法調用另一個有事務的方法,事務是不會起作用的。

特別注意第6點:同一個類中一個無事務的方法調用另一個有事務的方法,事務是不會起作用的。這一點引起了我的注意,可能我的加了注解@Transactional的departingCar方法也是被類里另一個沒有開啟事務的方法調用,如果真的是這樣,所有一切都解釋的通了。

果然,departingCar方法被一個沒加事務的接口方法調用,從而整個方法都沒有事務效果:

//此接口方法未加事務 @Overridepublic BizResult departingCarFlowFinish(CarDepartingForm form, User user) {···//在此調用事務方法BizResult departResult = departingCar(form, user);···}

解決方案

知道了引起問題的原因,解決方法也比較簡單,有好幾種方法都可以解決這個問題,本文列出其中兩種:
1.比較方便、暴力的一種方法就是直接在最外層接口方法中添加事務注解,也就是給本文中的departingCarFlowFinish方法加上注解即可。
2.也可以通過代理類調用departingCar方法,代理類中包含了事務邏輯,這樣也能實現事務功能。

轉載于:https://www.cnblogs.com/muxuanchan/p/11357953.html

總結

以上是生活随笔為你收集整理的记一次事务报错问题 Transaction synchronization is not active的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。