91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring接口方法加@Transactional失效如何解決

發布時間:2023-03-13 15:56:49 來源:億速云 閱讀:104 作者:iii 欄目:開發技術

這篇文章主要介紹了Spring接口方法加@Transactional失效如何解決的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Spring接口方法加@Transactional失效如何解決文章都會有所收獲,下面我們一起來看看吧。

問題

今天項目測試一個方法的時候,發現日志報錯

日志報錯大致如下:Connection is read-only. Queries leading to data modification are not allowed

org.springframework.dao.TransientDataAccessResourceException:
### Error updating database.  Cause: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
### The error may involve com.o2o.app.repository.AccountOrderMybatisDao.updateOrder-Inline
### The error occurred while setting parameters
### SQL: UPDATE t_account_order SET ORDER_STATUS=?, STATUS_DESCRIPTION=?, IS_DELETE = ?           WHERE  TRADE_CODE = ? and TRADE_TYPE=?
### Cause: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed; SQL []; Connection is 
read-only. Queries leading to data modification are not allowed; nested exception is java.sql.SQLException: 
Connectionis read-only. Queries leading to data modification are not allowed

第一眼看上去,這不是Spring事務配置了只讀事務屬性,當執行sql寫操作當然會失敗了,為了更好解決這個bug,讓我們先溫習一下事務以及Spring在事務傳播做了那些事?

  • 事務介紹

  • 事務(Transaction):指的是要做的事情,在計算機術語指的是訪問并能更新數據庫數據的一個程序執行單元

  • 由于我們日常開發,需要經常對關系型數據庫打交道,這里簡單介紹一下關系型數據庫的事務四大屬性

事務名稱解釋
原子性(Atomicity)事務是一個原子操作,原子操作簡單理解指的是這個操作要么全部成功,要么全部失敗
一致性(Consistency)事務無論成功與否,數據庫必須保證所處的數據不應被破壞,舉個例子:A給B無論成功或失敗轉賬,那么A的錢+B的錢前后應該總和相等
隔離性(Isolation)同一份的數據可能有很多事務進行操作,因此要將各種事務隔離開,防止數據被損壞
持久性(Durability)事務如果一旦完成,結果都應不變,因為這樣無論系統發送了什么錯誤,都能進行數據恢復
  • Spring事務核心類和接口

  • 如下圖所示:在spring-tx包下有三個spring事務管理非常重要的接口 : PlatformTransactionManager,TransactionDefinition,TransactionStatus

Spring接口方法加@Transactional失效如何解決


spring并不實現各個數據庫持久層的事務實現,而是提供對應的事務管理器,如下圖所示:

Spring接口方法加@Transactional失效如何解決


我們首先查看PlatformTransactionManager接口的源代碼:

Spring接口方法加@Transactional失效如何解決

TransactionStatus getTransaction(TransactionDefinition definition)

官方的解釋是: Return a currently active transaction or create a new one, according to the specified propagation behavior

這句話的意思是根據指定的事務行為,返回當前的事務或者新建一個事務。

void commit(TransactionStatus status)

官方解釋是:Commit the given transaction, with regard to its status. If the transaction has been marked rollback-only programmatically, perform a rollback.

這句話的意思是根據事務的狀態提交事務,如果事務標記了rollback-only,請執行會滾。

void rollback(TransactionStatus status)

官方的解釋是: Perform a rollback of the given transaction,即對事務進行回滾。

看到這里,我們需要明確三個接口中入參的TransactionDefinition是個什么東西呢?

讓我們先大致查看一下TransactionDefinition接口的方法和成員變量,以下將會對此接口的方法做個簡單的介紹,如下圖所示:

Spring接口方法加@Transactional失效如何解決

  • 事務的傳播行為

  • 當事務方法被調用時候,必須指定事務如何傳播,下面是事務傳播行為的介紹:

事務名稱解釋
PROPAGATION_REQUIRED支持當前的事務,如果當前事務不存在就新建一個事務
PROPAGATION_SUPPORTS支持當前事務,如果事務不存在,將以非事務方式運行
PROPAGATION_MANSATORY支持當前事務,如果事務不存在將拋異常
PROPAGATION_REQUIRES_NEW如果當前事務存在,將當前事務掛起并創建新的事務,如果當前事務不存在就新建一個事務
PROPAGATION_NOT_SUPPORTED不支持當前事務,以非事務的方式運行
PROPAGATION_NEVER不支持當前事務,如果當前事務存在就拋異常
PROPAGATION_NESTED如果當前事務存在,則執行一個內嵌的事務
  • 事務的隔離級別

  • 典型的事務隔離不同所造成問題如下:

1.臟讀:臟讀發送在A事務讀取B事務已經改寫但是還未提交的數據,若此時B事務回滾了,那么A事務獲取就是臟數據

2.不可重復讀:不可重復讀發送在當A事務執行2次查詢,每一次獲取的數據結果都不相同,這是由于B事務在A事務2次查詢期間進行了更新

3.幻讀: 幻讀發送在當A事務讀取了幾行數據,緊接著B事務進行輸入的插入,在隨后的查詢中A事務就會讀了原本不存在的記錄

不可重復讀特指修改的記錄,而幻讀指的是新增或刪除的記錄

  • 只讀屬性

  • 如果設置了只讀事務,只讀事務常常用于做查詢使用,此時的增刪改,將會報Connection is read-only. Queries leading to data modification are not allowed的異常。

  • 事務的超時

  • 一個正常和良好的程序,事務的行為時間并不會很長,較長的事務運行時間,會占用數據庫資源,所以這里就設置超時時間,若指定時間內沒有執行完事務,將會自動進行回滾

  • 事務的名稱

  • 在一個事務行為中配置獲取事務的名稱,如我們常見的save,add,del 等等…

以上溫習過Spring事務管理器和傳播行為后,所以既然報錯Connection is read-only. Queries leading to data modification are not allowed所以我們在接口方法的實現,加了以下的注解: @Transactional(propagation = Propagation.REQUIRED, readOnly = false),but!當我再次請求接口的時候,發現依然還是報同樣的錯誤,百度一下,發現有相關問題博客的收集:Spring下默認事務機制中@Transactional 無效的原因

Method visibility and @Transactional When using proxies, you should apply the @Transactional annotation 
only to methods with public visibility. If you do annotate protected, private or package-visible methods with the
@Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. 
Consider the use of AspectJ (see below) if you need to annotate non-public methods.

大概意思是:如果你是使用默認的Spring Aop代理方式將@Transaction注解應該用于公共可見即public的,如果對protected,或者private的方法加入@Transaction注解,則會無效。如果想在私有方法是使事務有效,可以用AspectJ進行實現。

but,我們的注解沒有加在protected和private方法上,但是依然無效,why?

此次注解失效原因像下面簡單的例子一樣:在電商系統中,存在待支付的訂單,假設有一個訂單編號為201904191102的訂單要進行支付,首先我需要刷新支付頁面,就需要調用收銀臺接口,由于一直使用的scala開發,所以下面的代碼使用scala做演示:

  /**
    * 刷新收銀臺的接口:refreshCashier
    */
  def refreshCashier(orderId: String): OrderInfo
  
    /**
    * 更新錢包的方法
    */
  def updateWallet(order:orderInfo):PayDto
  
  override def refreshCashier(orderId: String): OrderInfo = {
    // 偽代碼,在這個方法里面調用 updateWallet方法
  }
 @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
  override def updateWallet(order:orderInfo): PayDto = {
   // 這里發送了異常
   throw new AppException()
  }

在上面的代碼中,refreshCashier方法調用了updateWallet方法的時候,當updateWallet方法出錯報異常,事務并沒有回滾,這是因為Spring Aop動態代理會為每個class對象生成代理對象,只有在代理對象之間進行調用的時候,將會觸發切面相關的邏輯處理。

所以要保證整個方法調用鏈的事務性,在refreshCashier方法加上@Transaction注解,此時才能保證,updateWallet方法出錯時候,整個方法能進行事務的回滾。這樣完美,問題解決了.

關于“Spring接口方法加@Transactional失效如何解決”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“Spring接口方法加@Transactional失效如何解決”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

青海省| 思南县| 顺昌县| 阿拉尔市| 四平市| 县级市| 夏河县| 泾阳县| 乐东| 丘北县| 习水县| 徐闻县| 湖北省| 抚松县| 水富县| 潢川县| 郓城县| 巴马| 东兴市| 天津市| 威远县| 伊春市| 常德市| 彰武县| 阳新县| 志丹县| 黑龙江省| 长寿区| 富源县| 屏东市| 沿河| 四平市| 新乐市| 通道| 当雄县| 丘北县| 泾源县| 华亭县| 纳雍县| 舒兰市| 平顺县|