久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Spring事務(wù)管理詳解

 liang1234_ 2018-04-13

事務(wù)的基本原理

Spring事務(wù)的本質(zhì)其實就是數(shù)據(jù)庫對事務(wù)的支持,,使用JDBC的事務(wù)管理機制,就是利用java.sql.Connection對象完成對事務(wù)的提交,那在沒有Spring幫我們管理事務(wù)之前,,我們要怎么做。

Connection conn = DriverManager.getConnection(); try { conn.setAutoCommit(false); //將自動提交設(shè)置為false 執(zhí)行CRUD操作 conn.commit(); //當兩個操作成功后手動提交 } catch (Exception e) { conn.rollback(); //一旦其中一個操作出錯都將回滾,,所有操作都不成功 e.printStackTrace(); } finally { conn.colse(); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

事務(wù)是一系列的動作,,一旦其中有一個動作出現(xiàn)錯誤,,必須全部回滾,系統(tǒng)將事務(wù)中對數(shù)據(jù)庫的所有已完成的操作全部撤消,,滾回到事務(wù)開始的狀態(tài),,避免出現(xiàn)由于數(shù)據(jù)不一致而導(dǎo)致的接下來一系列的錯誤。事務(wù)的出現(xiàn)是為了確保數(shù)據(jù)的完整性和一致性,,在目前企業(yè)級應(yīng)用開發(fā)中,,事務(wù)管理是必不可少的。

與事務(wù)相關(guān)的理論知識

眾所周知,,事務(wù)有四大特性(ACID)

1.原子性(Atomicity)事務(wù)是一個原子操作,由一系列動作組成,。事務(wù)的原子性確保動作要么全部完成,,要么完全不起作用。

2.一致性(Consistency)事務(wù)在完成時,,必須是所有的數(shù)據(jù)都保持一致狀態(tài),。

3.隔離性(Isolation)并發(fā)事務(wù)執(zhí)行之間無影響,,在一個事務(wù)內(nèi)部的操作對其他事務(wù)是不產(chǎn)生影響,這需要事務(wù)隔離級別來指定隔離性,。

4.持久性(Durability)一旦事務(wù)完成,,數(shù)據(jù)庫的改變必須是持久化的。

在企業(yè)級應(yīng)用中,,多用戶訪問數(shù)據(jù)庫是常見的場景,,這就是所謂的事務(wù)的并發(fā),。事務(wù)并發(fā)所可能存在的問題:
1.臟讀:一個事務(wù)讀到另一個事務(wù)未提交的更新數(shù)據(jù),。
2.不可重復(fù)讀:一個事務(wù)兩次讀同一行數(shù)據(jù),可是這兩次讀到的數(shù)據(jù)不一樣,。
3.幻讀:一個事務(wù)執(zhí)行兩次查詢,,但第二次查詢比第一次查詢多出了一些數(shù)據(jù)行,。
4.丟失更新:撤消一個事務(wù)時,把其它事務(wù)已提交的更新的數(shù)據(jù)覆蓋了,。

我們可以在java.sql.Connection中看到JDBC定義了五種事務(wù)隔離級別來解決這些并發(fā)導(dǎo)致的問題:

/** * A constant indicating that transactions are not supported. */ int TRANSACTION_NONE = 0; /** * A constant indicating that * dirty reads, non-repeatable reads and phantom reads can occur. * This level allows a row changed by one transaction to be read * by another transaction before any changes in that row have been * committed (a 'dirty read'). If any of the changes are rolled back, * the second transaction will have retrieved an invalid row. */ int TRANSACTION_READ_UNCOMMITTED = 1; /** * A constant indicating that * dirty reads are prevented; non-repeatable reads and phantom * reads can occur. This level only prohibits a transaction * from reading a row with uncommitted changes in it. */ int TRANSACTION_READ_COMMITTED = 2; /** * A constant indicating that * dirty reads and non-repeatable reads are prevented; phantom * reads can occur. This level prohibits a transaction from * reading a row with uncommitted changes in it, and it also * prohibits the situation where one transaction reads a row, * a second transaction alters the row, and the first transaction * rereads the row, getting different values the second time * (a 'non-repeatable read'). */ int TRANSACTION_REPEATABLE_READ = 4; /** * A constant indicating that * dirty reads, non-repeatable reads and phantom reads are prevented. * This level includes the prohibitions in * <code>TRANSACTION_REPEATABLE_READ</code> and further prohibits the * situation where one transaction reads all rows that satisfy * a <code>WHERE</code> condition, a second transaction inserts a row that * satisfies that <code>WHERE</code> condition, and the first transaction * rereads for the same condition, retrieving the additional * 'phantom' row in the second read. */ int TRANSACTION_SERIALIZABLE = 8;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

翻譯過來這幾個常量就是
TRANSACTION_NONE JDBC 驅(qū)動不支持事務(wù)
TRANSACTION_READ_UNCOMMITTED 允許臟讀,、不可重復(fù)讀和幻讀,。
TRANSACTION_READ_COMMITTED 禁止臟讀,,但允許不可重復(fù)讀和幻讀。
TRANSACTION_REPEATABLE_READ 禁止臟讀和不可重復(fù)讀,,單運行幻讀。
TRANSACTION_SERIALIZABLE 禁止臟讀,、不可重復(fù)讀和幻讀,。

隔離級別越高,意味著數(shù)據(jù)庫事務(wù)并發(fā)執(zhí)行性能越差,,能處理的操作就越少,。你可以通過conn.setTransactionLevel去設(shè)置你需要的隔離級別,。
JDBC規(guī)范雖然定義了事務(wù)的以上支持行為,,但是各個JDBC驅(qū)動,,數(shù)據(jù)庫廠商對事務(wù)的支持程度可能各不相同,。
出于性能的考慮我們一般設(shè)置TRANSACTION_READ_COMMITTED就差不多了,剩下的通過使用數(shù)據(jù)庫的鎖來幫我們處理別的,,關(guān)于數(shù)據(jù)庫的鎖這個之后再說,。

了解了基本的JDBC事務(wù),那有了Spring,在事務(wù)管理上會有什么新的改變呢,?
有了Spring,,我們再也無需要去處理獲得連接,、關(guān)閉連接,、事務(wù)提交和回滾等這些操作,,使得我們把更多的精力放在處理業(yè)務(wù)上,。事實上Spring并不直接管理事務(wù),而是提供了多種事務(wù)管理器,。他們將事務(wù)管理的職責委托給Hibernate或者JTA等持久化機制所提供的相關(guān)平臺框架的事務(wù)來實現(xiàn),。

Spring事務(wù)管理

Spring事務(wù)管理的核心接口是PlatformTransactionManager
這里寫圖片描述
事務(wù)管理器接口通過getTransaction(TransactionDefinition definition)方法根據(jù)指定的傳播行為返回當前活動的事務(wù)或創(chuàng)建一個新的事務(wù),這個方法里面的參數(shù)是TransactionDefinition類,,這個類就定義了一些基本的事務(wù)屬性,。
在TransactionDefinition接口中定義了它自己的傳播行為和隔離級別
這里寫圖片描述
除去常量,主要的方法有:

int getIsolationLevel();// 返回事務(wù)的隔離級別 String getName();// 返回事務(wù)的名稱 int getPropagationBehavior();// 返回事務(wù)的傳播行為 int getTimeout(); // 返回事務(wù)必須在多少秒內(nèi)完成 boolean isReadOnly(); // 事務(wù)是否只讀,,事務(wù)管理器能夠根據(jù)這個返回值進行優(yōu)化,,確保事務(wù)是只讀的
  • 1
  • 2
  • 3
  • 4
  • 5

Spring事務(wù)的傳播屬性

由上圖可知,Spring定義了7個以PROPAGATION_開頭的常量表示它的傳播屬性,。

名稱 解釋
PROPAGATION_REQUIRED 0 支持當前事務(wù),,如果當前沒有事務(wù),,就新建一個事務(wù),。這是最常見的選擇,,也是Spring默認的事務(wù)的傳播,。
PROPAGATION_SUPPORTS 1 支持當前事務(wù),,如果當前沒有事務(wù),,就以非事務(wù)方式執(zhí)行,。
PROPAGATION_MANDATORY 2 支持當前事務(wù),,如果當前沒有事務(wù),就拋出異常,。
PROPAGATION_REQUIRES_NEW 3 新建事務(wù),,如果當前存在事務(wù),把當前事務(wù)掛起,。
PROPAGATION_NOT_SUPPORTED 4 以非事務(wù)方式執(zhí)行操作,如果當前存在事務(wù),就把當前事務(wù)掛起,。
PROPAGATION_NEVER 5 以非事務(wù)方式執(zhí)行,,如果當前存在事務(wù),則拋出異常,。
PROPAGATION_NESTED 6 如果當前存在事務(wù),,則在嵌套事務(wù)內(nèi)執(zhí)行,。如果當前沒有事務(wù),,則進行與PROPAGATION_REQUIRED類似的操作,。

Spring事務(wù)的隔離級別

名稱 解釋
ISOLATION_DEFAULT -1 這是一個PlatfromTransactionManager默認的隔離級別,,使用數(shù)據(jù)庫默認的事務(wù)隔離級別。另外四個與JDBC的隔離級別相對應(yīng)
ISOLATION_READ_UNCOMMITTED 1 這是事務(wù)最低的隔離級別,,它充許另外一個事務(wù)可以看到這個事務(wù)未提交的數(shù)據(jù),。這種隔離級別會產(chǎn)生臟讀,,不可重復(fù)讀和幻讀。
ISOLATION_READ_COMMITTED 2 保證一個事務(wù)修改的數(shù)據(jù)提交后才能被另外一個事務(wù)讀取,。另外一個事務(wù)不能讀取該事務(wù)未提交的數(shù)據(jù),。
ISOLATION_REPEATABLE_READ 4 這種事務(wù)隔離級別可以防止臟讀,不可重復(fù)讀,。但是可能出現(xiàn)幻讀。
ISOLATION_SERIALIZABLE 8 這是花費最高代價但是最可靠的事務(wù)隔離級別,。事務(wù)被處理為順序執(zhí)行。除了防止臟讀,,不可重復(fù)讀外,還避免了幻讀,。

調(diào)用PlatformTransactionManager接口的getTransaction()的方法得到的是TransactionStatus接口的一個實現(xiàn)
TransactionStatus接口
這里寫圖片描述
主要的方法有:

void flush();//如果適用的話,,這個方法用于刷新底層會話中的修改到數(shù)據(jù)庫,,例如,,所有受影響的Hibernate/JPA會話。 boolean hasSavepoint(); // 是否有恢復(fù)點 boolean isCompleted();// 是否已完成 boolean isNewTransaction(); // 是否是新的事務(wù) boolean isRollbackOnly(); // 是否為只回滾 void setRollbackOnly(); // 設(shè)置為只回滾
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

可以看出返回的結(jié)果是一些事務(wù)的狀態(tài),,可用來檢索事務(wù)的狀態(tài)信息。

配置事務(wù)管理器

介紹完Spring事務(wù)的管理的流程大概是怎么走的,。接下來可以動手試試Spring是如何配置事務(wù)管理器的
例如我在spring-mybatis中配置的:

<!-- 配置事務(wù)管理器 --> <bean id='transactionManager' class='org.springframework.jdbc.datasource.DataSourceTransactionManager'> <property name='dataSource' ref='dataSource' /> </bean>
  • 1
  • 2
  • 3
  • 4

這配置不是唯一的,,可以根據(jù)自己項目選擇的數(shù)據(jù)訪問框架靈活配置事務(wù)管理器

配置了事務(wù)管理器后,事務(wù)當然還是得我們自己去操作,,Spring提供了兩種事務(wù)管理的方式:編程式事務(wù)管理和聲明式事務(wù)管理,,讓我們分別看看它們是怎么做的吧。

編程式事務(wù)管理

編程式事務(wù)管理我們可以通過PlatformTransactionManager實現(xiàn)來進行事務(wù)管理,,同樣的Spring也為我們提供了模板類TransactionTemplate進行事務(wù)管理,,下面主要介紹模板類,我們需要在配置文件中配置

<!--配置事務(wù)管理的模板--> <bean id='transactionTemplate' class='org.springframework.transaction.support.TransactionTemplate'> <property name='transactionManager' ref='transactionManager'></property> <!--定義事務(wù)隔離級別,-1表示使用數(shù)據(jù)庫默認級別--> <property name='isolationLevelName' value='ISOLATION_DEFAULT'></property> <property name='propagationBehaviorName' value='PROPAGATION_REQUIRED'></property> </bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

TransactionTemplate幫我們封裝了許多代碼,,節(jié)省了我們的工作,。下面我們寫個單元測試來測測。
為了測試事務(wù)回滾,,專門建了一張tbl_accont表,,用于模擬存錢的一個場景。service層主要代碼如下,,后面會給出全部代碼的github地址,,有需要的朋友請移步查看。
BaseSeviceImpl

//方便測試直接寫的sql @Override public void insert(String sql, boolean flag) throws Exception { dao.insertSql(sql); // 如果flag 為 true ,,拋出異常 if (flag){ throw new Exception('has exception!!!'); } } //獲取總金額 @Override public Integer sum(){ return dao.sum(); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

dao對應(yīng)的sum方法

<select id='sum' resultType='java.lang.Integer'> SELECT SUM(money) FROM tbl_account; </select>
  • 1
  • 2
  • 3

下面看看測試代碼

package com.gray; import com.gray.service.BaseSevice; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; import javax.annotation.Resource; /** * Created by gray on 2017/4/8. */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {'classpath:spring-test.xml'}) public class TransactionTest{ @Resource private TransactionTemplate transactionTemplate; @Autowired private BaseSevice baseSevice; @Test public void transTest() { System.out.println('before transaction'); Integer sum1 = baseSevice.sum(); System.out.println('before transaction sum: ' sum1); System.out.println('transaction....'); transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { try{ baseSevice.insert('INSERT INTO tbl_account VALUES (100);',false); baseSevice.insert('INSERT INTO tbl_account VALUES (100);',false); } catch (Exception e){ //對于拋出Exception類型的異常且需要回滾時,需要捕獲異常并通過調(diào)用status對象的setRollbackOnly()方法告知事務(wù)管理器當前事務(wù)需要回滾 status.setRollbackOnly(); e.printStackTrace(); } } }); System.out.println('after transaction'); Integer sum2 = baseSevice.sum(); System.out.println('after transaction sum: ' sum2); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

當baseSevice.insert的第二個參數(shù)為false時,,我們假設(shè)插入數(shù)據(jù)沒有出現(xiàn)任何問題,測試結(jié)果如圖所示:
這里寫圖片描述
當?shù)诙€參數(shù)為true時,,insert會拋出一個異常,,這是事務(wù)就應(yīng)該回滾,數(shù)據(jù)前后不應(yīng)該有變化,,如圖所示:
這里寫圖片描述

聲明式事務(wù)管理

聲明式事務(wù)管理有兩種常用的方式,,一種是基于tx和aop命名空間的xml配置文件,一種是基于@Transactional注解,,隨著Spring和Java的版本越來越高,,大家越趨向于使用注解的方式,下面我們兩個都說,。
1.基于tx和aop命名空間的xml配置文件
配置文件

<tx:advice id='advice' transaction-manager='transactionManager'> <tx:attributes> <tx:method name='insert' propagation='REQUIRED' read-only='false' rollback-for='Exception'/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id='pointCut' expression='execution (* com.gray.service.*.*(..))'/> <aop:advisor advice-ref='advice' pointcut-ref='pointCut'/> </aop:config>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

測試代碼

@Test public void transTest() { System.out.println('before transaction'); Integer sum1 = baseSevice.sum(); System.out.println('before transaction sum: ' sum1); System.out.println('transaction....'); try{ baseSevice.insert('INSERT INTO tbl_account VALUES (100);',true); } catch (Exception e){ e.printStackTrace(); } System.out.println('after transaction'); Integer sum2 = baseSevice.sum(); System.out.println('after transaction sum: ' sum2); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

事務(wù)正常執(zhí)行結(jié)果截圖
這里寫圖片描述
事務(wù)出現(xiàn)異常結(jié)果截圖
這里寫圖片描述
2.基于@Transactional注解
這種方式最簡單,,也是最為常用的,只需要在配置文件中開啟對注解事務(wù)管理的支持,。

<!-- 聲明式事務(wù)管理 配置事物的注解方式注入--> <tx:annotation-driven transaction-manager='transactionManager'/>
  • 1
  • 2

然后在需要事務(wù)管理的地方加上@Transactional注解,,如:

@Transactional(rollbackFor=Exception.class) public void insert(String sql, boolean flag) throws Exception { dao.insertSql(sql); // 如果flag 為 true ,拋出異常 if (flag){ throw new Exception('has exception!!!'); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

rollbackFor屬性指定出現(xiàn)Exception異常的時候回滾,,遇到檢查性的異常需要回滾,,默認情況下非檢查性異常,包括error也會自動回滾,。
測試代碼和上面那個一樣
事務(wù)正常執(zhí)行結(jié)果截圖
這里寫圖片描述
事務(wù)出現(xiàn)異常結(jié)果截圖
這里寫圖片描述
以上就是對Spring事務(wù)進行了詳細的分析和代碼示例,。
最后是測試代碼Spring事務(wù)測試

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多