javascript
html调用接口_Spring 自调用事务失效,你是怎么解决的?
前言
" 相信大家都遇到一種事務失效場景,那就是 Spring 自調用,就是在 Service 方法內,調用另一個加 @Transactional 注解的方法,發現事務失效,這時候你是怎么解決的呢? "
1
事情回顧
那是一個我忘了天氣咋樣的下午,突然蹦出一個小紅點,嗯~ 挺著急的小紅點。
原來是事務失效了!
莫慌!莫慌!
最后小伙伴選擇了抽走,是我的工具類不香了么?
當然故事的結果是完美的,問題解決了。
2
事務
在開發中涉及到同時操作多個表的時候,要保證兩個操作要么一起成功,要么一起失敗,這時候就需要用到事務。
現在一般使用的都是基于 @Transactional 注解的聲明式事務。
而事務使用過程中有以下幾個注意事項:
當然這幾句話不是說我的,人家官方文檔可是明確說明的!
這里可是說明了應僅將 @Transactional 注解應用于具有公開可見性的方法。如果對受 protected, private o或 package-visible 修飾的方法使用,則不會引發任何錯誤,但是被注解的方法不會顯示已配置的事務設置。
說白了,就是你用了,不會報錯,但是不生效!
至于建議加在實現類上,這個只是建議,不過如果加在接口類或接口方法上時,只有配置基于接口的代理才會生效。所以這塊還是老老實實的加在實現類或實現類方法上吧。
因為代理模式只攔截通過代理傳入的外部方法調用,所以自調用事務是不生效的。
官方的解釋還是比較簡單明了的,雖然我看不懂,但是不影響我截圖。
那我還是再截一個吧……
3
實際使用
但是在開發中,小伙伴們往往會遇到這種情況!
本來自己寫的代碼就一坨坨的又臭又長,里面有各種驗簽、驗參、查詢、驗證等等,就想著來個事務,讓事務包裹的范圍最小,僅僅在同時更新的時候加上事務吧!
這么寫,咦~ IDEA 報錯了,好像不能 private 修飾,那我改成 public。
很顯然事務是不生效的。
把更新的代碼放到又臭又長的代碼里面,讓它變得更臭更長,然后用 @Transactional 注解一加。完美解決!
請放過那坨代碼吧!來看看下面的辦法。
解決方案 1
那我改成外部調用不就行了么?
再聲明一個 Service,把更新表的邏輯放過去。
我一般就喜歡使用這個辦法。
解決方案 2
使用編程式事務,前面說了,使用聲明式事務時,又這又那,我換一種總可以吧!
你看,我還把方法改成 private 修飾了,事務也生效。完美解決!
其實這個方法也很不錯哦!
解決方案 3
又想用注解,又想自調用怎么辦?
不過... 麻煩一點還是可以的。
咱們可以參考編程式事務的方式,不就是不讓自調用么,我調外部方法,然后外部方法再給我調回來不就可以了。
@Componentpublic?class?TransactionalComponent?{????public?interface?Cell?{????????void?run()?throws?Exception;????}????@Transactional(propagation?=?Propagation.REQUIRED,?rollbackFor?=?Exception.class)????public?void?required(Cell?cell)?throws?Exception?{????????cell.run();????}}這樣的話不就可以通過 TransactionalComponent 調用了么,并且還可以使用 lambda 表達式。
當然基于這個版本也可以做一個迭代,就是使用靜態方法調用,不用每次都用 @Autowired 注入一次。
public?class?TransactionalUtils?{????????private?static?volatile?TransactionalComponent?transactionalComponent;????private?static?synchronized?TransactionalComponent?getTransactionalComponent()?{????????if?(transactionalComponent?==?null)?{????????????//?從容器中獲取?transactionalComponent????????????transactionalComponent?=?ApplicationContextUtils.getBean(TransactionalComponent.class);????????}????????return?transactionalComponent;????}????public?static?void?required(TransactionalComponent.Cell?cell)?throws?Exception?{????????getTransactionalComponent().required(cell);????}}這樣通過工具類 TransactionalUtils 便可以直接調用靜態方法的方式執行事務操作。
4
總結
結束語
本文主要介紹為什么會遇到事務失效,以及事務失效的避免方式,同時提供了三種方式來解決自調用事務失效的問題。不足之處,歡迎指正。
相關資料
[1] Spring 文檔:
https://docs.spring.io/spring-framework/docs/5.3.0/reference/html/data-access.html#transaction-declarative-annotations
- -
作者:劉志航,一個宅宅的北漂程序員。
公眾號:liuzhihangs,記錄工作學習中的技術、開發及源碼筆記;時不時分享一些生活中的見聞感悟。歡迎大佬來指導!
總結
以上是生活随笔為你收集整理的html调用接口_Spring 自调用事务失效,你是怎么解决的?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python列表逐行写入excel_py
- 下一篇: 微信网页开发教程 php,PHP实现微信