在前面的文章中總結了spring事務的5中配置方式,但是很多方式都不用而且當時的配置使用的所有參數都是默認的參數,這篇文章就看常用的兩種事務配置方式並信息配置事務的傳播性、隔離級別、以及超時等問題,廢話不說下面就來看看!
一、註解式事務
1、註解式事務在平時的開發中使用的挺多,工作的兩個公司中看到很多項目使用了這種方式,下面看看具體的配置demo。
2、事務配置實例
(1)、spring+mybatis 事務配置
(2)、spring+hibernate 事務配置
看到上面的這兩段配置文件是不是很熟悉,對的這就是我們平時看到的事務的配置,在spring的配置中配置數據源即dataSource、事務管理器,事務管理器使用不同的orm框架事務管理器類就不同,比如這裏使用的是mybatis 所以是
如果使用hibernate 則事務管理器類爲
這是使用註解方式時要配置的,代碼中的具體的註解以及事務的傳播性、隔離級別一般在service 層中配置下面看看
3、@Transactional
(1)、這裏說明一下,有的把這個註解放在類名稱上面了,這樣你配置的這個@Transactional 對這個類中的所有public方法都起作用
(2)、@Transactional 方法方法名上,只對這個方法有作用,同樣必須是public的方法
比如這裏就對這個方法定義了一個事務同時設置了很多屬性:
(1)、事務的傳播性:@Transactional(propagation=Propagation.REQUIRED)
如果有事務, 那麼加入事務, 沒有的話新建一個(默認情況下)
(2)、事務的超時性:@Transactional(timeout=30) //默認是30秒
注意這裏說的是事務的超時性而不是Connection的超時性,這兩個是有區別的
(3)、事務的隔離級別:@Transactional(isolation = Isolation.READ_UNCOMMITTED)
讀取未提交數據(會出現髒讀, 不可重複讀) 基本不使用
(4)、回滾:
指定單一異常類:@Transactional(rollbackFor=RuntimeException.class)
指定多個異常類:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
該屬性用於設置需要進行回滾的異常類數組,當方法中拋出指定異常數組中的異常時,則進行事務回滾。(5)、只讀:@Transactional(readOnly=true)
該屬性用於設置當前事務是否爲只讀事務,設置爲true表示只讀,false則表示可讀寫,默認值爲false。
ok 這種註解方式實現事務的配置以及一些屬性的定義,其實事務的東西還有很多要注意的事項,如果要深入學習的話要學習的東西還很多,這裏只是簡單記錄一下
那我們要注意什麼那:
1、在spring配置文件中引入<tx:>命名空間:xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
2、@Transactional 只能被應用到public方法上, 對於其它非public的方法,如果標記了@Transactional也不會報錯,但方法沒有事務功能.
3、用 spring 事務管理器,由spring來負責數據庫的打開,提交,回滾.默認遇到運行期例外(throw new RuntimeException("註釋");)會回滾,即遇到不受檢查(unchecked)的例外時回滾;而遇到需要捕獲的例外(throw new Exception("註釋");)不會回滾,即遇到受檢查的例外(就是非運行時拋出的異常,編譯器會檢查到的異常叫受檢查例外或說受檢查異常)時,需我們指定方式來讓事務回滾 要想所有異常都回滾,要加上 @Transactional( rollbackFor={Exception.class,其它異常})
.如果讓unchecked例外不回滾: @Transactional(notRollbackFor=RunTimeException.class)
如下:
@Transactional(rollbackFor=Exception.class) //指定回滾,遇到異常Exception時回滾
public void methodName() {
throw new Exception("註釋");
}
@Transactional(noRollbackFor=Exception.class)//指定不回滾,遇到運行期例外(throw new RuntimeException("註釋");)會回滾
public ItimDaoImpl getItemDaoImpl() {
throw new RuntimeException("註釋");
}
4、@Transactional 註解應該只被應用到 public 可見度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 註解,它也不會報錯, 但是這個被註解的方法將不會展示已配置的事務設置。
5、@Transactional 註解可以被應用於接口定義和接口方法、類定義和類的 public 方法上。然而,請注意僅僅 @Transactional 註解的出現不足於開啓事務行爲,它僅僅 是一種元數據,能夠被可以識別 @Transactional 註解和上述的配置適當的具有事務行爲的beans所使用。上面的例子中,其實正是 <tx:annotation-driven/>元素的出現 開啓 了事務行爲。
6、Spring團隊的建議是你在具體的類(或類的方法)上使用 @Transactional 註解,而不要使用在類所要實現的任何接口上。你當然可以在接口上使用 @Transactional 註解,但是這將只能當你設置了基於接口的代理時它才生效。因爲註解是 不能繼承 的,這就意味着如果你正在使用基於類的代理時,那麼事務的設置將不能被基於類的代理所識別,而且對象也將不會被事務代理所包裝(將被確認爲嚴重的)。因 此,請接受Spring團隊的建議並且在具體的類上使用 @Transactional 註解。
二、使用AOP的方式實現事務的配置
1、這種事務使用也很多,下面我們來看看簡單的例子
2、事務配置實例:
(1)、配置文件
上面我們看到了,簡單的配置了事務,其中tx:attributes中設置了事務的傳播性,隔離級別以及那種問題能進行回滾超時等這些問題,也就是你自己按照業務需求定製一個事務來滿足你的業務需求。
注意: 這裏注意一下,在tx:method中配置了rollback_for 中配置的Exception 這個是運行時的異常纔會回滾不然其他異常是不會回滾的!
這裏我們看到了,如果拋出的是一個運行時異常則會回滾而如果拋出的不是運行時異常則會不回滾的。
需要注意的地方:
(1)、在spring 配置文件中引入:xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
(2) advice(建議)的命名:由於每個模塊都會有自己的Advice,所以在命名上需要作出規範,初步的構想就是模塊名+Advice(只是一種命名規範)。
(3) tx:attribute標籤所配置的是作爲事務的方法的命名類型。
如<tx:method name="save*" propagation="REQUIRED"/>
其中*爲通配符,即代表以save爲開頭的所有方法,即表示符合此命名規則的方法作爲一個事務。
propagation="REQUIRED"代表支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。
(4) aop:pointcut標籤配置參與事務的類,由於是在Service中進行數據庫業務操作,配的應該是包含那些作爲事務的方法的Service類。
首先應該特別注意的是id的命名,同樣由於每個模塊都有自己事務切面,所以我覺得初步的命名規則因爲 all+模塊名+ServiceMethod。而且每個模塊之間不同之處還在於以下一句:
expression="execution(* com.test.testAda.test.model.service.*.*(..))"
其中第一個*代表返回值,第二*代表service下子包,第三個*代表方法名,“(..)”代表方法參數。
(5) aop:advisor標籤就是把上面我們所配置的事務管理兩部分屬性整合起來作爲整個事務管理。
(6)注意標紅的地方
ok 到這裏兩種配置方式簡單的demo 都有了,下面我們來看看tx:method 中還有那些屬性可以配置
下面來看看aop 這種方式來配置的時候我們還能配置那些屬性:
<tx:advice id="advice" transaction-manager="txManager">
<tx:attributes>
<!-- tx:method的屬性:
* name 是必須的,表示與事務屬性關聯的方法名(業務方法名),對切入點進行細化。通配符(*)可以用來指定一批關聯到相同的事務屬性的方法。
如:'get*'、'handle*'、'on*Event'等等.
* propagation 不是必須的 ,默認值是REQUIRED
表示事務傳播行爲, 包括REQUIRED,SUPPORTS,MANDATORY,REQUIRES_NEW,NOT_SUPPORTED,NEVER,NESTED
* isolation 不是必須的 默認值DEFAULT
表示事務隔離級別(數據庫的隔離級別)
* timeout 不是必須的 默認值-1(永不超時)
表示事務超時的時間(以秒爲單位)
* read-only 不是必須的 默認值false不是隻讀的
表示事務是否只讀?
* rollback-for 不是必須的
表示將被觸發進行回滾的 Exception(s);以逗號分開。
如:'com.foo.MyBusinessException,ServletException'
* no-rollback-for 不是必須的
表示不被觸發進行回滾的 Exception(s);以逗號分開。
如:'com.foo.MyBusinessException,ServletException'
任何 RuntimeException 將觸發事務回滾,但是任何 checked Exception 將不觸發事務回滾
-->
<tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
<tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
<tx:method name="delete*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
<!-- 其他的方法之只讀的 -->
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
OK 兩種配置方式我們也都簡單學習了,兩種配置方式有哪些屬性要配置我們也瞭解了,但是,這裏只是說了有這兩種常用的方法,而沒有具體說事務以及事務的配置帶來的數據的安全性以及性能的影響,其實事務不是那麼簡單,具體深入學習希望以後有總結!
下面給大家列出spring事務的幾種傳播特性:
Spring事務的隔離級別
事務的隔離級別和數據庫中是一樣的大家可以看數據庫事務隔離級別就能明白了但是事務的傳播性是個什麼鬼貌似之前沒聽過那下面就來看看
拷貝文章:http://blog.sina.com.cn/s/blog_4b5bc0110100z7jr.html
我們都知道事務的概念,那麼事務的傳播特性是什麼呢?(此處着重介紹傳播特性的概念,關於傳播特性的相關配置就不介紹了,可以查看spring的官方文檔)在我們用SSH開發項目的時候,我們一般都是將事務設置在Service層 那麼當我們調用Service層的一個方法的時候它能夠保證我們的這個方法中執行的所有的對數據庫的更新操作保持在一個事務中,在事務層裏面調用的這些方法要麼全部成功,要麼全部失敗。那麼事務的傳播特性也是從這裏說起的。如果你在你的Service層的這個方法中,除了調用了Dao層的方法之外,還調用了本類的其他的Service方法,那麼在調用其他的Service方法的時候,這個事務是怎麼規定的呢,我必須保證我在我方法裏掉用的這個方法與我本身的方法處在同一個事務中,否則如果保證事物的一致性。事務的傳播特性就是解決這個問題的,“事務是會傳播的”在Spring中有針對傳播特性的多種配置我們大多數情況下只用其中的一種:PROPGATION_REQUIRED:這個配置項的意思是說當我調用service層的方法的時候開啓一個事務(具體調用那一層的方法開始創建事務,要看你的aop的配置),那麼在調用這個service層裏面的其他的方法的時候,如果當前方法產生了事務就用當前方法產生的事務,否則就創建一個新的事務。這個工作使由Spring來幫助我們完成的。以前沒有Spring幫助我們完成事務的時候我們必須自己手動的控制事務,例如當我們項目中僅僅使用hibernate,而沒有集成進spring的時候,我們在一個service層中調用其他的業務邏輯方法,爲了保證事物必須也要把當前的hibernate session傳遞到下一個方法中,或者採用ThreadLocal的方法,將session傳遞給下一個方法,其實都是一個目的。現在這個工作由spring來幫助我們完成,就可以讓我們更加的專注於我們的業務邏輯。而不用去關心事務的問題。默認情況下當發生RuntimeException的情況下,事務纔會回滾,所以要注意一下 如果你在程序發生錯誤的情況下,有自己的異常處理機制定義自己的Exception,必須從RuntimeException類繼承 這樣事務纔會回滾!