【踩坑】Shiro和Mybatis整合,事務失效 will not be managed by Spring

[速記] 踩坑

今天一下午都在找這個bug,發現平時用的好好的mybatis,居然突然就事務失效了、
當然我想大家第一反應就是@Transaction註解的一些注意要點,這些我也簡單在這貼一下吧:
spring管理的事務,其實就是靠aop來對數據庫操作方法的前後進行處理。
我理解的spring做的事情如下:
spring織布機前後織入了邏輯(生成類的代理對象)

public void springAop(){

//1. 獲取連接,設置事務爲手動提交
try{
//2. 執行業務代碼
excute();
}catch(Exception e){
  //回滾
}
//提交
}

所以我們理解爲怎麼讓aop生效就可以了

  1. 自然需要spring管理,所以需要加上@Service或者@Component註解
  2. 自然需要spring反射調用,所以方法必須爲public,不能爲final
  3. 這個調用的過程必須能被切點pointcut捕捉到,所以this對象自己調用自己的方法是不會被aop捕捉到的
對於事務,有接口實現類A,有方法a1和a2, 和接口實現類B有方法b1和b2
1. 如果方法不是public修飾,無法使用事務
2. 如果不能使用aop代理,比如設置final關鍵字的類
3. 如果其他接口通過aop調用a1,a1有事務,則事務有效,不管a1內部調用或外部調用其他方法
4. 如果其他接口通過aop調用a1,a1沒有事務,a1調用a2,a2有事務,事務不生效.
5. 如果其他接口通過aop調用a1,a1有事務,a1調用a2,a2拋出異常,a1或a2去try catch,事務不生效
6. 如果其他接口通過aop調用a1,a1有事務,a1調用b1,默認的話b1會因爲REQUIRED傳播機制,進入到a1的事務中,事務生效
7. 如果其他接口通過aop調用a1,a1有事務,a1調用b1,b1拋出異常,a1捕捉異常,事務生效會回滾,但是會拋出異常`Transaction rolled back because it has been marked as rollback-only`,
這是因爲因爲B已經拋出異常了,B所在的事務是REQUIRED,也就是會加入A的事務,導致A的事務是標記回滾狀態的,A try catch 內部處理了異常,
會執行提交操作,但是提交標記了回滾異常的會導致最終回滾
**解決方法: A繼續拋出異常,或者B內部try catch 或者B開啓新事務**

回到正題

好了對於經常使用spring和aop的人來說,我上面說的都是廢話,重要的來了,我怎麼排查原因都還是事務失效,甚至一度認爲是mybatis-plus升到3.x的鍋,因爲我之前項目用的2.x,還特地降級再試發現還是一樣。

最後想到什麼問題都可以從日誌中解決,所以我把日誌等級設置爲debug
同時開啓了mybatis的日誌打印

mybatis-plus:
	  #原生配置
  configuration:
  	log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

然後我看到了這條信息
在這裏插入圖片描述
what???這個jdbc連接沒有被spring接管?我要的就是spring的事務啊,所以大概就是這裏出問題了。
最後嘗試網上各種方法無果,最後看到一個博客,附上連接:
SpringBoot+Shiro引起事務失效、錯誤原因、解決方法
一看,大概意思就是我的Shiro中,reaml類裏面使用了UserService等依賴對象,這個時候它會比spring一般的初始化實例要早,而spring的實例都是單例的,也就是上面的spring織布機還沒來得及把前後處理事務的代碼織入進去,shiro初始化就把這兩個類的代理對象生成了,而對象只會實例化一次,所以就出現那條

JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@2af8253a] will not be managed by Spring

解決辦法原博客也提出來了
要麼在reaml類中使用mapper接口
要麼使用@lazy指定懶加載

問題解決

發佈了145 篇原創文章 · 獲贊 193 · 訪問量 59萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章