最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解讀Spring接口方法加@Transactional失效的原因

 更新時(shí)間:2023年03月13日 14:28:10   作者:Galen-gao  
這篇文章主要介紹了Spring接口方法加@Transactional失效的原因解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

問(wèn)題

今天項(xiàng)目測(cè)試一個(gè)方法的時(shí)候,發(fā)現(xiàn)日志報(bào)錯(cuò)

日志報(bào)錯(cuò)大致如下: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事務(wù)配置了只讀事務(wù)屬性,當(dāng)執(zhí)行sql寫(xiě)操作當(dāng)然會(huì)失敗了,為了更好解決這個(gè)bug,讓我們先溫習(xí)一下事務(wù)以及Spring在事務(wù)傳播做了那些事?

  • 事務(wù)介紹
  • 事務(wù)(Transaction):指的是要做的事情,在計(jì)算機(jī)術(shù)語(yǔ)指的是訪問(wèn)并能更新數(shù)據(jù)庫(kù)數(shù)據(jù)的一個(gè)程序執(zhí)行單元
  • 由于我們?nèi)粘i_(kāi)發(fā),需要經(jīng)常對(duì)關(guān)系型數(shù)據(jù)庫(kù)打交道,這里簡(jiǎn)單介紹一下關(guān)系型數(shù)據(jù)庫(kù)的事務(wù)四大屬性
事務(wù)名稱解釋
原子性(Atomicity)事務(wù)是一個(gè)原子操作,原子操作簡(jiǎn)單理解指的是這個(gè)操作要么全部成功,要么全部失敗
一致性(Consistency)事務(wù)無(wú)論成功與否,數(shù)據(jù)庫(kù)必須保證所處的數(shù)據(jù)不應(yīng)被破壞,舉個(gè)例子:A給B無(wú)論成功或失敗轉(zhuǎn)賬,那么A的錢+B的錢前后應(yīng)該總和相等
隔離性(Isolation)同一份的數(shù)據(jù)可能有很多事務(wù)進(jìn)行操作,因此要將各種事務(wù)隔離開(kāi),防止數(shù)據(jù)被損壞
持久性(Durability)事務(wù)如果一旦完成,結(jié)果都應(yīng)不變,因?yàn)檫@樣無(wú)論系統(tǒng)發(fā)送了什么錯(cuò)誤,都能進(jìn)行數(shù)據(jù)恢復(fù)
  • Spring事務(wù)核心類和接口
  • 如下圖所示:在spring-tx包下有三個(gè)spring事務(wù)管理非常重要的接口 : PlatformTransactionManager,TransactionDefinition,TransactionStatus


spring并不實(shí)現(xiàn)各個(gè)數(shù)據(jù)庫(kù)持久層的事務(wù)實(shí)現(xiàn),而是提供對(duì)應(yīng)的事務(wù)管理器,如下圖所示:


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

TransactionStatus getTransaction(TransactionDefinition definition)

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

這句話的意思是根據(jù)指定的事務(wù)行為,返回當(dāng)前的事務(wù)或者新建一個(gè)事務(wù)。

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.

這句話的意思是根據(jù)事務(wù)的狀態(tài)提交事務(wù),如果事務(wù)標(biāo)記了rollback-only,請(qǐng)執(zhí)行會(huì)滾。

void rollback(TransactionStatus status)

官方的解釋是: Perform a rollback of the given transaction,即對(duì)事務(wù)進(jìn)行回滾。

看到這里,我們需要明確三個(gè)接口中入?yún)⒌腡ransactionDefinition是個(gè)什么東西呢?

讓我們先大致查看一下TransactionDefinition接口的方法和成員變量,以下將會(huì)對(duì)此接口的方法做個(gè)簡(jiǎn)單的介紹,如下圖所示:

  • 事務(wù)的傳播行為
  • 當(dāng)事務(wù)方法被調(diào)用時(shí)候,必須指定事務(wù)如何傳播,下面是事務(wù)傳播行為的介紹:
事務(wù)名稱解釋
PROPAGATION_REQUIRED支持當(dāng)前的事務(wù),如果當(dāng)前事務(wù)不存在就新建一個(gè)事務(wù)
PROPAGATION_SUPPORTS支持當(dāng)前事務(wù),如果事務(wù)不存在,將以非事務(wù)方式運(yùn)行
PROPAGATION_MANSATORY支持當(dāng)前事務(wù),如果事務(wù)不存在將拋異常
PROPAGATION_REQUIRES_NEW如果當(dāng)前事務(wù)存在,將當(dāng)前事務(wù)掛起并創(chuàng)建新的事務(wù),如果當(dāng)前事務(wù)不存在就新建一個(gè)事務(wù)
PROPAGATION_NOT_SUPPORTED不支持當(dāng)前事務(wù),以非事務(wù)的方式運(yùn)行
PROPAGATION_NEVER不支持當(dāng)前事務(wù),如果當(dāng)前事務(wù)存在就拋異常
PROPAGATION_NESTED如果當(dāng)前事務(wù)存在,則執(zhí)行一個(gè)內(nèi)嵌的事務(wù)
  • 事務(wù)的隔離級(jí)別
  • 典型的事務(wù)隔離不同所造成問(wèn)題如下:

1.臟讀:臟讀發(fā)送在A事務(wù)讀取B事務(wù)已經(jīng)改寫(xiě)但是還未提交的數(shù)據(jù),若此時(shí)B事務(wù)回滾了,那么A事務(wù)獲取就是臟數(shù)據(jù)

2.不可重復(fù)讀:不可重復(fù)讀發(fā)送在當(dāng)A事務(wù)執(zhí)行2次查詢,每一次獲取的數(shù)據(jù)結(jié)果都不相同,這是由于B事務(wù)在A事務(wù)2次查詢期間進(jìn)行了更新

3.幻讀: 幻讀發(fā)送在當(dāng)A事務(wù)讀取了幾行數(shù)據(jù),緊接著B(niǎo)事務(wù)進(jìn)行輸入的插入,在隨后的查詢中A事務(wù)就會(huì)讀了原本不存在的記錄

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

  • 只讀屬性
  • 如果設(shè)置了只讀事務(wù),只讀事務(wù)常常用于做查詢使用,此時(shí)的增刪改,將會(huì)報(bào)Connection is read-only. Queries leading to data modification are not allowed的異常。
  • 事務(wù)的超時(shí)
  • 一個(gè)正常和良好的程序,事務(wù)的行為時(shí)間并不會(huì)很長(zhǎng),較長(zhǎng)的事務(wù)運(yùn)行時(shí)間,會(huì)占用數(shù)據(jù)庫(kù)資源,所以這里就設(shè)置超時(shí)時(shí)間,若指定時(shí)間內(nèi)沒(méi)有執(zhí)行完事務(wù),將會(huì)自動(dòng)進(jìn)行回滾
  • 事務(wù)的名稱
  • 在一個(gè)事務(wù)行為中配置獲取事務(wù)的名稱,如我們常見(jiàn)的save,add,del 等等…

以上溫習(xí)過(guò)Spring事務(wù)管理器和傳播行為后,所以既然報(bào)錯(cuò)Connection is read-only. Queries leading to data modification are not allowed所以我們?cè)诮涌诜椒ǖ膶?shí)現(xiàn),加了以下的注解: @Transactional(propagation = Propagation.REQUIRED, readOnly = false),but!當(dāng)我再次請(qǐng)求接口的時(shí)候,發(fā)現(xiàn)依然還是報(bào)同樣的錯(cuò)誤,百度一下,發(fā)現(xiàn)有相關(guān)問(wèn)題博客的收集:Spring下默認(rèn)事務(wù)機(jī)制中@Transactional 無(wú)效的原因

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.

大概意思是:如果你是使用默認(rèn)的Spring Aop代理方式將@Transaction注解應(yīng)該用于公共可見(jiàn)即public的,如果對(duì)protected,或者private的方法加入@Transaction注解,則會(huì)無(wú)效。如果想在私有方法是使事務(wù)有效,可以用AspectJ進(jìn)行實(shí)現(xiàn)。

but,我們的注解沒(méi)有加在protected和private方法上,但是依然無(wú)效,why?

此次注解失效原因像下面簡(jiǎn)單的例子一樣:在電商系統(tǒng)中,存在待支付的訂單,假設(shè)有一個(gè)訂單編號(hào)為201904191102的訂單要進(jìn)行支付,首先我需要刷新支付頁(yè)面,就需要調(diào)用收銀臺(tái)接口,由于一直使用的scala開(kāi)發(fā),所以下面的代碼使用scala做演示:

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

在上面的代碼中,refreshCashier方法調(diào)用了updateWallet方法的時(shí)候,當(dāng)updateWallet方法出錯(cuò)報(bào)異常,事務(wù)并沒(méi)有回滾,這是因?yàn)镾pring Aop動(dòng)態(tài)代理會(huì)為每個(gè)class對(duì)象生成代理對(duì)象,只有在代理對(duì)象之間進(jìn)行調(diào)用的時(shí)候,將會(huì)觸發(fā)切面相關(guān)的邏輯處理。

所以要保證整個(gè)方法調(diào)用鏈的事務(wù)性,在refreshCashier方法加上@Transaction注解,此時(shí)才能保證,updateWallet方法出錯(cuò)時(shí)候,整個(gè)方法能進(jìn)行事務(wù)的回滾。這樣完美,問(wèn)題解決了.

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring Cloud Feign實(shí)例講解學(xué)習(xí)

    Spring Cloud Feign實(shí)例講解學(xué)習(xí)

    這篇文章主要介紹了Spring Cloud Feign實(shí)例講解學(xué)習(xí),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • Java 基礎(chǔ)--Arrays工具類詳解

    Java 基礎(chǔ)--Arrays工具類詳解

    這篇文章主要介紹了Java Arrays工具類用法,結(jié)合實(shí)例形式分析了java Arrays工具類針對(duì)數(shù)組元素修改、復(fù)制、排序等操作使用技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2021-09-09
  • 擴(kuò)展Hibernate使用自定義數(shù)據(jù)庫(kù)連接池的方法

    擴(kuò)展Hibernate使用自定義數(shù)據(jù)庫(kù)連接池的方法

    這篇文章主要介紹了擴(kuò)展Hibernate使用自定義數(shù)據(jù)庫(kù)連接池的方法,涉及Hibernate數(shù)據(jù)庫(kù)操作擴(kuò)展的相關(guān)技巧,需要的朋友可以參考下
    2016-03-03
  • Redis有效時(shí)間設(shè)置以及時(shí)間過(guò)期處理操作

    Redis有效時(shí)間設(shè)置以及時(shí)間過(guò)期處理操作

    這篇文章主要介紹了Redis有效時(shí)間設(shè)置以及時(shí)間過(guò)期處理操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-11-11
  • Java 動(dòng)態(tài)代理你真的懂了嗎(動(dòng)態(tài)和代理)

    Java 動(dòng)態(tài)代理你真的懂了嗎(動(dòng)態(tài)和代理)

    動(dòng)態(tài)代理分兩部分,動(dòng)態(tài)和代理,今天通過(guò)本文給大家普及代碼模式及動(dòng)態(tài)代理的概念及示例代碼,感興趣的朋友跟隨小編一起看看吧
    2021-07-07
  • 兩行Javascript代碼生成UUID的方法

    兩行Javascript代碼生成UUID的方法

    這篇文章主要介紹了兩行Javascript代碼生成UUID的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Java類加載機(jī)制實(shí)現(xiàn)步驟解析

    Java類加載機(jī)制實(shí)現(xiàn)步驟解析

    這篇文章主要介紹了Java類加載機(jī)制實(shí)現(xiàn)步驟解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • HashMap原理及手寫(xiě)實(shí)現(xiàn)部分區(qū)塊鏈特征

    HashMap原理及手寫(xiě)實(shí)現(xiàn)部分區(qū)塊鏈特征

    這篇文章主要為大家介紹了HashMap原理及手寫(xiě)實(shí)現(xiàn)部分區(qū)塊鏈特征,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 利用java實(shí)現(xiàn)中獎(jiǎng)概率詳情

    利用java實(shí)現(xiàn)中獎(jiǎng)概率詳情

    這篇文章主要介紹了利用java實(shí)現(xiàn)中獎(jiǎng)概率詳情,根據(jù)概率將獎(jiǎng)品劃分區(qū)間,每個(gè)區(qū)間代表一個(gè)獎(jiǎng)品,然后抽取???隨機(jī)數(shù)??,反查落在那個(gè)區(qū)間上,即為所抽取的獎(jiǎng)品,需要的朋友可以參考一下
    2022-07-07
  • spring boot springMVC擴(kuò)展配置實(shí)現(xiàn)解析

    spring boot springMVC擴(kuò)展配置實(shí)現(xiàn)解析

    這篇文章主要介紹了spring boot springMVC擴(kuò)展配置實(shí)現(xiàn)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08

最新評(píng)論

西乌珠穆沁旗| 临漳县| 台江县| 淮安市| 锦屏县| 孟州市| 鄄城县| 三亚市| 岳普湖县| 华坪县| 同德县| 扎兰屯市| 凤冈县| 涟源市| 揭阳市| 邓州市| 康平县| 奎屯市| 苏尼特右旗| 平山县| 松滋市| 吴江市| 丹凤县| 名山县| 武夷山市| 惠安县| 乌鲁木齐县| 通辽市| 抚远县| 丰原市| 镇赉县| 七台河市| 霍城县| 株洲县| 曲松县| 淮滨县| 淮滨县| 雅江县| 历史| 寻乌县| 永和县|