當前位置:編程學習大全網 - 源碼下載 - 狗腿源代碼

狗腿源代碼

本周壹,公司來了壹位新同事。他在面試中表現很好,回答了各種問題。我的老板和我都非常高興。

這麽優秀的人壹定不能讓他浪費壹分鐘,所以很快,我就把需求文檔和源代碼發給他,讓他在本地熟悉業務和開發流程。

結果沒想到,周三我們在做壹個復習代碼的時候發現了壹個問題。新同事直接把原來的@Transactional優化成了這個ghost:

因為這壹行代碼,老板(當年也是壹線互聯網廠商的好手)當場就火了,他正要去勸這個新同事,我就趕緊拿定了主意。畢竟自己面試的人不是看和尚的臉而是佛的臉吧?所以老板答應我再試壹個月。

會後,我趕緊讓新同事回顧了壹下事務。以下是他自己的總結,還是很詳細的。我分享壹下,供大家參考和啟發。相信看完之後妳就明白為什麽不能這樣優化@Transactional的註釋了,純粹是畫蛇添足,不分青紅皂白。

事務在邏輯上是壹組操作,要麽執行,要麽不執行。主要針對數據庫,比如MySQL。

只要記住這壹點,就很容易理解交易。在Java中,我們通常要處理業務中的多個事件。比如編程喵有壹個保存文章的方法,不僅保存了文章本身,還保存了文章對應的標簽。標簽和文章不在同壹個表中,但是標簽表(標簽)通過在文章表(文章)中保存標簽主鍵(tag_id)來關聯:

那麽這個時候妳就需要啟動事務,保證article表和tag表中的數據是同步的,或者都執行或者都不執行。

否則可能是文章保存成功,但是標簽失敗,或者是文章保存失敗,標簽保存成功——這些場景都不符合我們的預期。

為了確保事務的正確性和可靠性,在寫入或更新數據庫時,必須顯示ACID的四個重要特征:

其中,事務隔離分為四個不同的級別,包括:

需要註意的是,事務能否生效取決於數據庫引擎是否支持事務。MySQL的InnoDB引擎支持事務,但MyISAM不支持。

1)程序化交易

程序化事務是指在業務代碼中嵌入事務管理代碼,控制事務提交和回滾。

例如,您使用TransactionTemplate來管理事務:

再舉壹個例子,使用TransactionManager管理事務:

就編程式事務管理而言,Spring更喜歡使用TransactionTemplate。

在程序化事務中,每個業務操作都必須包含額外的事務管理代碼,這使得代碼看起來非常臃腫,但對理解Spring的事務管理模型非常有幫助。

當然,要實現事務管理和業務代碼分離,必須使用Spring中最關鍵、最核心的技術之壹——AOP。其本質是前後截取方法,然後在目標方法開始前創建或加入壹個事務,在目標方法執行後根據執行情況提交或回滾。

Spring將事務管理的核心抽象為TransactionManager,其源代碼只有壹個簡單的接口定義,屬於壹個標記接口:

通過PlatformTransactionManager接口,Spring為各種平臺提供了相應的事務管理器,如JDBC(DatasourceTransactionManager)、Hibernate(Hibernate transaction manager)、JPA(JpaTransactionManager)等。,但具體實現是各平臺的事。

參數TransactionDefinition對應於@Transactional註釋。例如,在@Transactional批註中定義的屬性,如事務傳播行為、隔離級別、事務超時以及事務是否只讀,都可以在TransactionDefinition中找到。

返回類型TransactionStatus主要用於存儲當前事務的壹些狀態和數據,比如連接和回滾狀態。

TransactionDefinition.java:

Transactional.java

說到這裏,我們來詳細解釋壹下Spring事務的傳播行為、隔離級別、超時時間、只讀屬性和回滾規則。

當壹個事務方法被另壹個事務方法調用時,有必要指定事務應該如何傳播。例如,該方法可能會在當前事務中繼續執行,或者它可能會打開壹個新事務以在自己的事務中執行。

TransactionDefinition-* *定義了七種事務傳播行為:

01、傳播_必需

這也是@Transactional默認的事務傳播行為,也就是說如果壹個事務當前存在,就會被添加;如果當前沒有事務,則創建壹個新事務。更準確地說,它意味著:

這種傳播行為也最容易理解。aMethod調用bMethod,只要其中壹個方法回滾,整個事務就回滾。

02、傳播_要求_新

創建壹個新的事務,並掛起當前的事務(如果有的話)。也就是說,不管外部方法是否打開事務,傳播修飾的內部方法。REQUIRES_NEW _ New會打開自己的事務,打開的事務和外部事務是獨立的,互不幹擾。

如果aMethod()異常回滾,bMethod()不會回滾,因為bMethod()啟動了壹個獨立的事務。但是,如果bMethod()拋出壹個未捕獲的異常,並且這個異常符合事務回滾規則,那麽aMethod()也會回滾。

03、傳播_嵌套

如果當前有事務,則在當前事務內執行;否則,將執行類似於PROPAGATION_REQUIRED的操作。

04、傳播_強制

如果當前有交易,則加入交易;如果沒有當前事務,則會引發異常。

05、傳播_支持

如果當前有交易,則加入交易;如果當前沒有事務,它將繼續以非事務方式運行。

06、不支持傳播

以非事務方式運行,如果有事務,則掛起當前事務。

07、傳播_從不

以非事務方式運行,如果當前有事務,則拋出異常。

3,4,5,6,7不常用,知道就好。

我們已經了解了數據庫的事務隔離級別,理解Spring的事務隔離級別就容易多了。

TransactionDefinition中的* * *定義了五個事務隔離級別:

通常我們只是使用默認的隔離級別ISOLATION_DEFAULT,也就是交給數據庫來決定,我們可以選擇@ @ transaction _ isolation命令查看MySql的默認隔離級別,結果是REPEATABLE-READ,意思是可重復讀取。

事務超時,即事務被允許執行的最長時間,如果在超時期限內沒有完成,將自動回滾。

如果事務的執行時間特別長,因為事務涉及到鎖數據庫,會導致長時間運行的事務占用數據庫資源。

如果壹個事務只讀取數據庫,那麽數據庫可以利用事務的只讀特性,采取優化措施,這適合於多個數據庫查詢操作。

這是因為MySql(innodb)默認為每個連接啟用了自動提交模式。在這種模式下,發送到MySql服務器的每壹條SQL語句都將在壹個單獨的事務中處理,事務在執行後會自動提交。

然後如果我們用@Transactional註釋這個方法,這個方法中的所有SQL都將放在壹個事務中。否則每個SQL會單獨打開壹個事務,其他事務修改的數據會被實時讀取。

在某些情況下,當同時執行多個查詢語句並且需要保證數據壹致性時,需要啟用事務支持。否則,上壹次SQL查詢後,數據被其他用戶更改,那麽下壹次SQL查詢可能會不壹致。

默認情況下,事務僅在運行時異常發生時回滾,而當檢查異常(需要主動捕獲或拋出)發生時,錯誤不會回滾。

如果您想回滾特定的異常類型,可以這樣設置它:

在過去,我們需要配置Spring來通過XML管理事務。有了Spring Boot,壹切都變得簡單了。我們只需要在業務層添加交易評論(@Transactional)就可以快速打開交易。

換句話說,我們只需要關註@Transactional註釋。

盡管在@Transactional註釋源代碼中定義了許多屬性,但大多數時候,我使用默認配置。當然,如果需要定制的話,上面已經說明了。

1)要在public方法上使用,abstractfallbackTransactionAttributeSource類的computeTransactionAttribute方法中有壹個判斷。如果目標方法不是公共的,則TransactionAttribute返回null,即不支持該事務。

2)避免在同壹個類中調用@Transactional批註的方法,這樣會導致事務失效。

在測試之前,我們首先調整Spring Boot的默認日誌級別信息,以便在application.yml文件中進行調試和修改:

然後,看修改前找到的數據:

讓我們開始吧。給控制器增加壹個更新界面,準備修改數據,打算把寂靜之王2的狗腿修改成寂靜之王2的狗腿:

在服務中用@Transactional註釋該方法,並引發運行時異常:

根據我們的預期,在保存數據後,事務將因為壹個異常而回滾。所以數據不會被修改。

在瀏覽器中輸入http://localhost:8080/user/update進行測試,註意日誌確認交易已經生效。

當我們移除事務時,我們還會拋出壹個異常:

再次執行時,發現雖然程序報錯,但數據還是更新了。

這也間接證明了我們的@Transactional事務是行得通的。

看到這裏,妳明白為什麽新同事的優化純屬多余了吧?

  • 上一篇:優美句子:妳見過最美好的女生是什麽樣的
  • 下一篇:網頁體積的大小對做seo有影響嗎
  • copyright 2024編程學習大全網