❶ .spring的事務有幾種方式談談spring事務的隔離級別和傳播行為
1、 Propagation
key屬性確定代理應該給哪個方法增加事務行為。這樣的屬性最重要的部份是傳播行為。有以下選項可供使用:
PROPAGATION_REQUIRED--支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。
PROPAGATION_SUPPORTS--支持當前事務,如果當前沒有事務,就以非事務方式執行。
PROPAGATION_MANDATORY--支持當前事務,如果當前沒有事務,就拋出異常。
PROPAGATION_REQUIRES_NEW--新建事務,如果當前存在事務,把當前事務掛起。
PROPAGATION_NOT_SUPPORTED--以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
PROPAGATION_NEVER--以非事務方式執行,如果當前存在事務,則拋出異常。
2、 Isolation Level(事務隔離等級):
1、Serializable:最嚴格的級別,事務串列執行,資源消耗最大;
2、REPEATABLE READ:保證了一個事務不會修改已經由另一個事務讀取但未提交(回滾)的數據。避免了「臟讀取」和「不可重復讀取」的情況,但是帶來了更多的性能損失。
3、READ COMMITTED:大多數主流資料庫的默認事務等級,保證了一個事務不會讀到另一個並行事務已修改但未提交的數據,避免了「臟讀取」。該級別適用於大多數系統。
4、Read Uncommitted:保證了讀取過程中不會讀取到非法數據。
隔離級別在於處理多事務的並發問題。我們知道並行可以提高資料庫的吞吐量和效率,但是並不是所有的並發事務都可以並發運行,這需要查看資料庫教材的可串列化條件判斷了。
❷ 事務的幾種傳播特性及隔離級別
如果沒有事務則開啟 2. PROPAGATION_SUPPORTS: 如果存在一個事務,支持當前事務。如果沒有事務,則非事務的執行 3. PROPAGATION_MANDATORY: 如果已經存在一個事務,支持當前事務。如果沒有一個活動的事務,則拋出異常。 4. PROPAGATION_REQUIRES_NEW: 總是開啟一個新的事務。如果一個事務已經存在,則將這個存在的事務掛起。 5. PROPAGATION_NOT_SUPPORTED: 總是非事務地執行,並掛起任何存在的事務。 6. PROPAGATION_NEVER: 總是非事務地執行,如果存在一個活動事務,則拋出異常 7. PROPAGATION_NESTED:如果一個活動的事務存在,則運行在一個嵌套的事務中. 如果沒有活動事務, 則按TransactionDefinition.PROPAGATION_REQUIRED 屬性執行 2、Spring事務的隔離級別 1. ISOLATION_DEFAULT: 這是一個PlatfromTransactionManager默認的隔離級別,使用資料庫默認的事務隔離級別. 另外四個與JDBC的隔離級別相對應 2. ISOLATION_READ_UNCOMMITTED: 這是事務最低的隔離級別,它充許令外一個事務可以看到這個事務未提交的數據。 這種隔離級別會產生臟讀,不可重復讀和幻像讀。 3. ISOLATION_READ_COMMITTED: 保證一個事務修改的數據提交後才能被另外一個事務讀取。另外一個事務不能讀取該事務未提交的數據 4. ISOLATION_REPEATABLE_READ: 這種事務隔離級別可以防止臟讀,不可重復讀。但是可能出現幻像讀。 它除了保證一個事務不能讀取另一個事務未提交的數據外,還保證了避免下面的情況產生(不可重復讀)。 5. ISOLATION_SERIALIZABLE 這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。 除了防止臟讀,不可重復讀外,還避免了幻像讀。
❸ spring的事務傳播行為,究竟意義何在
其實通常下,spring事務的傳播行為和隔離級[transaction behaviorand isolatedlevel]都是互相配合,共同使用才能將spring事務運用到極致,事務的傳播行為就是一個個的事務策略而已,具體運用哪一個,根據自己的需求和程序性能平衡去抉擇,意義何在?
意義是大大的,由於不能保證系統絕對不出錯,所以當出錯的時候,應該講之前所處理的事情全部回退到事件發生之前,包括對資料庫這些修改等等,這是最為簡單的場景,當然還有事務之間的交互,比如A事務失敗了,會不會影響B事務,A事務捕獲B事務的異常,這時候應該怎麼辦,要不要回滾,還有一些其他情況,這些都需要spring事務傳播行為的支持。
❹ SpringBoot 資料庫事務7種傳播行為
如果當前方法的執行上下文中已經打開了事務,那麼就使用當前這個事務。
如果當前沒有事務,就創建一個新的。
如果多個方法都聲明了 REQUIRED ,並且他們嵌套調用,那麼他們會共享同一個物理事務。就是 inner 產生了回滾,那麼 outer 會跟著回滾。
Outer bean
Inner bean
inner 聲明了 REQUIRED ,並拋出了異常,outer 事務將同樣回滾,因為他們是同一個事務。
聲明 REQUIRES_NEW 的話就會創建一個新的物理事務,內層事務的提交回滾都是獨立於外層事務的。外層事務不受內層事務結果的影響,他們運行於獨立的物理事務。
Outer bean
Inner bean
inner 的回滾不影響 outer 的事務。當 inner 事務開啟後,outer 事務會暫停,當 inner 事務結束後,outer 事務恢復。
NESTED 使嵌套的事務使用相同的物理事務,但是對嵌套調用設置了保存點,所以 inner 事務可以獨立於 outer 事務回滾。
支持事務,如果當前存在事務,就沿用當前事務,如果不存在,則繼續採用無事務的方式運行。
必須使用事務。如果當前沒有事務,則會拋出異常,如果存在當前事務,就沿用當前事務。
不支持事務,當前存在事務時,將掛起事務,運行方法。
不支持事務,如果當前方法存在事務,則拋出異常,否則繼續使用無事務機制運行。
參考:
https://www.byteslounge.com/tutorials/spring-transaction-propagation-tutorial
❺ 程序員新人周一優化一行代碼,周三被勸退
這周一,公司新來了一個同事,面試的時候表現得非常不錯,各種問題對答如流,老闆和我都倍感欣慰。
這么優秀的人,絕不能讓他浪費一分一秒,於是很快,我就發他了需求文檔、源碼,讓他先在本地熟悉一下業務和開發流程。
結果沒想到,周三大家一塊 review 代碼的時候就發現了問題,新來的同事直接把原來 @Transactional 優化成了這個鬼樣子:
就因為這一行代碼,老闆(當年也是一線互聯網大廠的好手)當場就發飆了,馬上就要勸退這位新同事,我就趕緊打圓場,畢竟自己面試的人,不看僧面看佛面,是吧?於是老闆答應我說再試用一個月看看。
會議結束後,我就趕緊讓新同事復習了一遍事務,以下是他自己做的總結,還是非常詳細的,分享出來給大家一點點參考和啟發。相信大家看完後就明白為什麼不能這樣優化 @Transactional 註解了,純屬畫蛇添足和亂用。
事務在邏輯上是一組操作, 要麼執行,要不都不執行 。主要是針對資料庫而言的,比如說 Mysql。
只要記住這一點,理解事務就很容易了。在 Java 中,我們通常要在業務裡面處理多個事件,比如說編程喵有一個保存文章的方法,它除了要保存文章本身之外,還要保存文章對應的標簽,標簽和文章不在同一個表裡,但會通過在文章表裡(posts)保存標簽主鍵(tag_id)來關聯標簽表(tags):
那麼此時就需要開啟事務,保證文章表和標簽表中的數據保持同步,要麼都執行,要麼都不執行。
否則就有可能造成,文章保存成功了,但標簽保存失敗了,或者文章保存失敗了,標簽保存成功了——這些場景都不符合我們的預期。
為了保證事務是正確可靠的,在資料庫進行寫入或者更新操作時,就必須得表現出 ACID 的 4 個重要特性:
其中,事務隔離又分為 4 種不同的級別,包括:
需要格外注意的是: 事務能否生效,取決於資料庫引擎是否支持事務,MySQL 的 InnoDB 引擎是支持事務的,但 MyISAM 就不支持 。
1)編程式事務
編程式事務是指將事務管理代碼嵌入嵌入到業務代碼中,來控制事務的提交和回滾。
你比如說,使用 TransactionTemplate 來管理事務:
再比如說,使用 TransactionManager 來管理事務:
就編程式事務管理而言,Spring 更推薦使用 TransactionTemplate。
在編程式事務中,必須在每個業務操作中包含額外的事務管理代碼,就導致代碼看起來非常的臃腫,但對理解 Spring 的事務管理模型非常有幫助。
當然了,要想實現事務管理和業務代碼的抽離,就必須得用到 Spring 當中最關鍵最核心的技術之一,AOP,其本質是對方法前後進行攔截,然後在目標方法開始之前創建或者加入一個事務,執行完目標方法之後根據執行的情況提交或者回滾。
Spring 將事務管理的核心抽象為一個事務管理器(TransactionManager),它的源碼只有一個簡單的介面定義,屬於一個標記介面:
通過 PlatformTransactionManager 這個介面,Spring 為各個平台如 JDBC(DataSourceTransactionManager)、Hibernate(HibernateTransactionManager)、JPA(JpaTransactionManager)等都提供了對應的事務管理器,但是具體的實現就是各個平台自己的事情了。
參數 TransactionDefinition 和 @Transactional 註解是對應的,比如說 @Transactional 註解中定義的事務傳播行為、隔離級別、事務超時時間、事務是否只讀等屬性,在 TransactionDefinition 都可以找得到。
返回類型 TransactionStatus 主要用來存儲當前事務的一些狀態和數據,比如說事務資源(connection)、回滾狀態等。
TransactionDefinition.java:
Transactional.java
說到這,我們來詳細地說明一下 Spring 事務的傳播行為、事務的隔離級別、事務的超時時間、事務的只讀屬性,以及事務的回滾規則。
當事務方法被另外一個事務方法調用時,必須指定事務應該如何傳播 ,例如,方法可能繼續在當前事務中執行,也可以開啟一個新的事務,在自己的事務中執行。
TransactionDefinition 一共定義了 7 種事務傳播行為:
01、 PROPAGATION_REQUIRED
這也是 @Transactional 默認的事務傳播行為,指的是如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。更確切地意思是:
這個傳播行為也最好理解,aMethod 調用了 bMethod,只要其中一個方法回滾,整個事務均回滾。
02、 PROPAGATION_REQUIRES_NEW
創建一個新的事務,如果當前存在事務,則把當前事務掛起。也就是說不管外部方法是否開啟事務,Propagation.REQUIRES_NEW 修飾的內部方法都會開啟自己的事務,且開啟的事務與外部的事務相互獨立,互不幹擾。
如果 aMethod()發生異常回滾,bMethod()不會跟著回滾,因為 bMethod()開啟了獨立的事務。但是,如果 bMethod()拋出了未被捕獲的異常並且這個異常滿足事務回滾規則的話,aMethod()同樣也會回滾。
03、 PROPAGATION_NESTED
如果當前存在事務,就在當前事務內執行;否則,就執行與 PROPAGATION_REQUIRED 類似的操作。
04、 PROPAGATION_MANDATORY
如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。
05、 PROPAGATION_SUPPORTS
如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。
06、 PROPAGATION_NOT_SUPPORTED
以非事務方式運行,如果當前存在事務,則把當前事務掛起。
07、 PROPAGATION_NEVER
以非事務方式運行,如果當前存在事務,則拋出異常。
3、4、5、6、7 這 5 種事務傳播方式不常用,了解即可。
前面我們已經了解了資料庫的事務隔離級別,再來理解 Spring 的事務隔離級別就容易多了。
TransactionDefinition 中一共定義了 5 種事務隔離級別:
通常情況下,我們採用默認的隔離級別 ISOLATION_DEFAULT 就可以了,也就是交給資料庫來決定,可以通過 SELECT @@transaction_isolation; 命令來查看 MySql 的默認隔離級別,結果為 REPEATABLE-READ,也就是可重復讀。
事務超時,也就是指一個事務所允許執行的最長時間,如果在超時時間內還沒有完成的話,就自動回滾。
假如事務的執行時間格外的長,由於事務涉及到對資料庫的鎖定,就會導致長時間運行的事務佔用資料庫資源。
如果一個事務只是對資料庫執行讀操作,那麼該資料庫就可以利用事務的只讀屬性,採取優化措施,適用於多條資料庫查詢操作中。
這是因為 MySql(innodb)默認對每一個連接都啟用了 autocommit 模式,在該模式下,每一個發送到 MySql 伺服器的 SQL 語句都會在一個單獨的事務中進行處理,執行結束後會自動提交事務。
那如果我們給方法加上了 @Transactional 註解,那這個方法中所有的 SQL 都會放在一個事務里。否則,每條 SQL 都會單獨開啟一個事務,中間被其他事務修改了數據,都會實時讀取到。
有些情況下,當一次執行多條查詢語句時,需要保證數據一致性時,就需要啟用事務支持。否則上一條 SQL 查詢後,被其他用戶改變了數據,那麼下一個 SQL 查詢可能就會出現不一致的狀態。
默認情況下,事務只在出現運行時異常(Runtime Exception)時回滾,以及 Error,出現檢查異常(checked exception,需要主動捕獲處理或者向上拋出)時不回滾。
如果你想要回滾特定的異常類型的話,可以這樣設置:
以前,我們需要通過 XML 配置 Spring 來託管事務,有了 Spring Boot 之後,一切就變得更加簡單了,只需要在業務層添加事務註解( @Transactional )就可以快速開啟事務。
也就是說,我們只需要把焦點放在 @Transactional 註解上就可以了。
雖然 @Transactional 註解源碼中定義了很多屬性,但大多數時候,我都是採用默認配置,當然了,如果需要自定義的話,前面也都說明過了。
1)要在 public 方法上使用,在類的computeTransactionAttribute方法中有個判斷,如果目標方法不是public,則TransactionAttribute返回null,即不支持事務。
2)避免同一個類中調用 @Transactional 註解的方法,這樣會導致事務失效。
在測試之前,我們先把 Spring Boot 默認的日誌級別 info 調整為 debug,在 application.yml 文件中 修改:
然後,來看修改之前查到的數據:
開搞。在控制器中添加一個 update 介面,准備修改數據,打算把沉默王二的狗腿子修改為沉默王二的狗腿:
在 Service 中為方法加上 @Transactional 註解並拋出運行時異常:
按照我們的預期,當執行 save 保存數據後,因為出現了異常,所以事務要回滾。所以數據不會被修改。
在瀏覽器中輸入 http://localhost:8080/user/update 進行測試,注意查看日誌,可以確認事務起效了。
當我們把事務去掉,同樣拋出異常:
再次執行,發現雖然程序報錯了,但數據卻被更新了。
這也間接地證明,我們的 @Transactional 事務起效了。
看到這,是不是就明白為什麼新同事的優化純屬畫蛇添足/卵用了吧?
❻ Spring支持的常用資料庫事務傳播屬性和隔離級別
那麼不知道你 對於Spring支持的常用資料庫事務傳播屬性和隔離級別 了解得怎麼樣呢?要不要一起復習復習了:grin:
很喜歡一句話:「八小時內謀生活,八小時外謀發展」
共勉 :woman: :computer:
描述 :進來先看看風景啦,要相信會有光的哦
對於資料庫事務ACID(原子性、一致性、隔離性、持久性)性質我想大家都是知道的,這里就不寫了:grin:
我們都知道用事務是為了保證資料庫的完整性,保證成批的 SQL 語句要麼全部執行,要麼全部不執行。
但是如果一個方法嵌套關聯著其他方法了,這該怎麼算呢?當前方法及關聯方法都有事務呢,或者只是其中某幾個有事務,該用誰的呢?
事務的傳播行為:一個方法運行在一個開啟了事務的方法上時,當前方法是使用原來的事務還是開啟一個新的事務。
通過 @Transaction 註解中 propagation 來設置事務傳播行為。其中
事務傳播行為總共有以下七種:
下面寫了一個小demo來讓理解更加快捷一些哈。
注意:account表中 balance 欄位是設置為無符號的(即不能為負數)。
項目就是普通Spring項目
模擬的是買書的一個過程,賬戶余額不足,但是一次買多本的情況,一起付款。
在其中再測試事務傳播行為的不同,來看數據的變化。
初始代碼:
mapper層代碼
測試一:默認事務傳播行為
我們在 void checkout(int userId, List isbns) 和 void purchase(int userId, int isbn) 上都加了 @Transactional
目前賬戶為 100元,兩本書的價格分別為 60和50 ,因為我們的付款過程是 使用循環 購買的,你說我們會買到一本還是一本都買不到呢?
答案當然是一本都買不到,因為 @Transactional 註解 ,默認事務的傳播屬性是:REQUIRED,即業務方法需要在一個事務中運行。如果方法運行時,已經處在一個事務中,那麼加入到該事務,否則為自己創建一個新的事務。所以實際上 void purchase(int userId, int isbn) 其實和調用它的方法用的同一個事務。簡單畫個圖:
測試二:測試 -->REQUIRES_NEW屬性
其他代碼未改變,僅在 purchase 上的註解上加了點東西 @Transactional(propagation = Propagation.REQUIRES_NEW) .
REQUIRES_NEW: 不管是否存在事務,業務方法總會為自己發起一個新的事務。如果方法已經運行在一個事務中,則原有事務會被掛起,新的事務會被創建,直到方法執行結束,新事務才算結束,原先的事務才會恢復執行。
你說說答案和上面是一樣的么?:grinning:
答案是不一樣的, 測試一 我們實際上用的就是checkout上的事務,並沒有用到 purchase 的事務,從圖上也能看出來。
測試二它的事務傳播屬性 用 圖來講是這樣的啦:
所以是可以買到一本書的。
還有很多,意思都解釋過了,沒有一一測完了。
假設現在有A和B 兩個事務 並發執行。
1)臟讀:一個事務讀取到另一事務未提交的更新新據
2)不可重復讀: 同一事務中,多次讀取同一數據返回的結果有所不同(針對的update操作)
3)幻讀:一個事務讀取到另一事務已提交的insert數據(針對的insert操作)
資料庫事務的隔離性: 資料庫系統必須具有隔離並發運行各個事務的能力, 使它們不會相互影響, 避免各種並發問題.
一個事務與其他事務隔離的程度稱為隔離級別. 資料庫規定了多種事務隔離級別, 不同隔離級別對應不同的干擾程度, 隔離級別越高, 數據一致性就越好, 但並發性越弱
在代碼中,我們可以通過
資料庫提供了4種隔離級別:
注 : 模擬並發情況。
1) 測試一下 mysql 的默認隔離級別:
測試代碼特別簡單,但因為我是手動模擬,得打斷點、debug啟動,
當執行完第一個 double bookPrice = bookShopMapper.getBookPriceByIsbn(isbn) 語句時,應該去mysql 修改一下書的價格,這樣看一下結果。
這個時候再接著執行。看輸出什麼。
最後的結果仍然是50、50。因為mysql的默認事務隔級別是可重復讀,意思在這同一個事務中,可以重復讀。
注 :因為這是直接修改資料庫,其操作行為並不可取,此處只是為了模擬。其結果有時也非一定準確。
❼ 什麼是事務的傳播特性
就是多個事務方法相互調用時,事務如何在這些方法間傳播。
❽ spring mvc 怎麼樣設置mysql事物隔離級別
先來總體說一下我對這個問題的理解,用一句話概括:
資料庫是可以控制事務的傳播和隔離級別的,Spring在之上又進一步進行了封裝,可以在不同的項目、不同的操作中再次對事務的傳播行為和隔離級別進行策略控制。
注意:Spring不僅可以控制事務傳播行為(PROPAGATION_REQUIRED等),還可以控制事務隔離級別(ISOLATION_READ_UNCOMMITTED等)。
(以下是個人理解,如果有瑕疵請及時指正)
下面我具體解釋一下:
為了大家能夠更好的理解,先來明確幾個知識點:
事務的傳播行為:簡單來說就是事務是手動提交還是自動提交,事務什麼時候開始,什麼時候提交。
事務的隔離級別:簡單來說,就四個,提交讀,提交讀,重復讀,序列化讀。
首先我來描述一下,資料庫(mysql)層面上對於事務傳播行為和隔離級別的配置和實驗方法:
資料庫層面(採用命令行):其實mySql命令行很簡單,希望實驗操作一下:
//連接資料庫,我這里是本地,後面是用戶名密碼,不要打分號,如果指令不行,配置下環境變數,網上有很多。
1. cmd中執行:mysql -hlocalhost -uroot -pmysql
//查看本地資料庫事務傳播行為是手動提交(0),還是自動提交(1)。
2.select @@autocommit;
//如果是0,希望設置為手動提交,這里其實是設置本對話的autocommit,因為如果你再開一個cmd,發現還是沒改回來,如果想修改全局的,網上有global方法。
3.set @@autocommit=0;
//然後查詢本地資料庫中的一條記錄,我本地資料庫為test1;
4.use test1;
5.select * from task where taskid=1;
//同時新開一個窗口cmd,連接資料庫,並且修改這條記錄,update語句我就不寫了,或者直接修改資料庫本條記錄。
//再次執行select * from task where taskid=1;發現值沒變。OK因為此時資料庫隔離級別為repeatable read 重復讀,因為mysql默認的隔離級別是重復讀。
//修改資料庫隔離級別
6.set global transaction isolation level read committed;
//查看一下,可能需要重新連接一下
7.select @@tx_isolation;
//這時在執行一下4,5操作,發現值變了,ok。因為已經改變了資料庫隔離級別,發生了重復讀出不同數據的現象。
(以上操作希望有不明白的上網自學一下,很有用,先把資料庫隔離級別弄明白了)
然後再來講一下,Spring對事務傳播行為和隔離級別的二次封裝。
因為不同項目可能在一個mysql的不同資料庫上,所以可以在項目中配置資料庫的傳播行為和隔離級別:
關於spring的傳播行為(PROPAGATION_REQUIRED、PROPAGATION_REQUIRED等),我《資料庫隔離級別(mysql+Spring)與性能分析 》文章中有講,網上也有很多相關資料,我就不說了。
關於spring的事務隔離級別與資料庫的一樣,也是那四個,多了一個default,我也不仔細講了。
下面主要講一下spring的配置方法:
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,ISOLATION_READ_UNCOMMITTED</prop>
</props>
就以find為例,可以配置這么配置,前面是控制傳播行為,後面是控制事務隔離級別的。那麼這時哪怕資料庫層面上是重復讀,但是還是以這里為准,你會發現在同一個事務中兩次查詢的結果是不一樣的。
最後掃除一個盲區,readonly這個屬性,是放在傳播行為中的,一般書都這么歸類,我也嘗試了一下,readonly並不能影響資料庫隔離級別,只是配置之後,不允許在事務中對資料庫進行修改操作,僅此而已。
❾ spring對循環操作資料庫時的事務處理如何配置
事務傳播級別設置為requiredNew
循環調用方法,每次調用方法都開啟新的事務保存數據
❿ 什麼是事務的傳播特性
在我們用SSH開發項目的時候,我們一般都是將事務設置在Service層
那麼當我們調用Service層的一個方法的時候它能夠保證我們的這個方法中執行的所有的對資料庫的更新操作保持在一個事務中,在事務層裡面調用的這些方法要麼全部成功,要麼全部失敗。那麼事務的傳播特性也是
從這里說起
的。
如果你在
你的Service層的這個方法中,除了調用了Dao層的方法之外,還調用了本類的其他的Service方法,那麼在調用其他的Service方法的時候,這個事務是怎麼規定的呢,我必須保證我在我方法里掉用的這個方法與我本身的方法處在同一個事務中,否則如果保證事物的一致性。事務的傳播特性就是解決這個問題的,「事務是會傳播的」在Spring中有針對傳播特性的多種配置我們大多數情況下只用其中的一種:PROPGATION_REQUIRED:這個
配置項
的意思是說當我調用service層的方法的時候開啟一個事務(具體調用那一層的方法開始創建事務,要看你的aop的配置),那麼在調用這個service層裡面的其他的方法的時候,如果當前方法產生了事務就用當前方法產生的事務,否則就創建一個新的事務。這個工作使由Spring來幫助我們完成的。
以前沒有Spring幫助我們完成事務的時候我們必須自己手動的控制事務,例如當我們項目中僅僅使用
hibernate
,而沒有集成進spring的時候,我們在一個service層中調用其他的
業務邏輯
方法,為了保證事物必須也要把當前的hibernate
session傳遞到下一個方法中,或者採用
ThreadLocal
的方法,將session傳遞給下一個方法,其實都是一個目的。現在這個工作由spring來幫助我們完成,就可以讓我們更加的專注於我們的業務邏輯。而不用去關心事務的問題。
默認情況下當發生Runtime
Exception
的情況下,事務才會
回滾
,所以要注意一下
如果你在程序發生錯誤的情況下,有自己的
異常處理
機制定義自己的Exception,必須從RuntimeException類繼承
這樣事務才會回滾!