以前說到Spring的事務管理 一直很懵逼 ,只知道事務管理大概是幹嗎的。spring
網上的博客都是用 銀行轉帳來解釋 事務管理,哈哈哈 那我也用這個吧,這個例子的確是最好的。數據庫
說是兩我的相互轉帳,A轉500塊錢給B,至於A爲啥轉錢給B那是她們直接的事情。那麼問題來了,好比A轉錢給B的時候,忽然斷電了,A 的錢已經從數據庫中扣了,但並無執行存入到B帳戶的操做。若是沒有事務管理,那這500快就沒了 但有了事務管理 那以前的這個從A扣的錢 就會回滾 本次操做 就不成功。因此A就不會扣錢 。至於原理是什麼,就見下回分享吧。express
言歸正傳。編程
Spring的事務管理分爲兩種:maven
1:編程式的事務管理性能
手動編寫代碼進行事務管理(不多使用)測試
2:聲明式的事務管理spa
2.1 基於TransactionProxyFactoryBean的方式(不多使用)。code
2.2 基於AspectJ的xml方式(常常使用)xml
2.3 基於註解@Transaction的方式(常常使用)
那麼咱們就來詳細說說 這幾種事務管理是怎麼實現的。
一:首先 咱們得先聊一聊事務的幾個要素
1:事務的傳播行爲,Propagation 。其主要的參數值有:
PROPAGATION_REQUIRED--支持當前事務,若是當前沒有事務,就新建一個事務。這是最多見的選擇。 (比較經常使用)
PROPAGATION_SUPPORTS--支持當前事務,若是當前沒有事務,就以非事務方式執行。
PROPAGATION_MANDATORY--支持當前事務,若是當前沒有事務,就拋出異常。
PROPAGATION_REQUIRES_NEW--新建事務,若是當前存在事務,把當前事務掛起。
PROPAGATION_NOT_SUPPORTED--以非事務方式執行操做,若是當前存在事務,就把當前事務掛起。
PROPAGATION_NEVER--以非事務方式執行,若是當前存在事務,則拋出異常。
2:事務的隔離級別:isolation
4: 發生哪些異常須要回滾:rollback-for (...Exprofesion)
5:發生哪些異常不回滾 no-rollback-for
6:timeout :過時信息
二:咱們從比較經常使用的聲明式事務管理開始介紹。
2.1 基於AspectJ的xml方式(常常使用)
基於AspectJ的和基於註解的事務管理都是採用AOP協助的事務管理方式。並且是Spring的項目,因此在Spring必要的jar包的基礎上來進行的
因此,首先咱們須要進入必要的jar包,這裏咱們採用的是maven引入相關jar包
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.1.6.RELEASE</version> </dependency> <dependency> <groupId>aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.4</version> </dependency> <dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.4</version> </dependency>
而後 咱們在Spring的配置文件中加入以下代碼:
首先是注入Spring的事務管理,由於因此的事務管理都是他來實現的。其中dataSourse是你的c3p0連接池,這裏就很少作介紹。
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
而後是配置事務的相關屬性
<!--基於aspectj的事務聲明式事務管理方式--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- propagation :事務傳播行爲 isolation :事務隔離級別 read-only :只讀 rollback-for :發生哪些異常須要回滾 no-rollback-for :發生哪些異常不回滾 timeout :過時信息 -->
<!--這個是須要進行事務的管理的那個方法名 這裏的name通常是 「sava*」 「update*」 list*」 表示以sava開始的方法都要進行事務的管理-->
<tx:method name="refnumber" propagation="REQUIRED" isolation="DEFAULT"/> </tx:attributes> </tx:advice>
而後就是進行AOP的切點和切面配置 這裏的切入點是 demo下面的servcie.impl的因此包的全部類中的因此方法
<aop:config proxy-target-class="true"> <!–配置切入點–> <aop:pointcut id="pointCut1" expression="execution(* demo.service.impl.*.*(..))"></aop:pointcut> <!–配置切面–> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut1"/> </aop:config>
因此 咱們就完成了事務管理的配置
測試以下:
在有異常的時候,第一步雖然執行了 但數據庫操做並無成功。
2.3 基於註解@Transaction的方式(常常使用)
這個方式 就更加簡單了
<!--事務管理--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--開啓註解--> <tx:annotation-driven transaction-manager="transactionManager"/>
在須要進行事務管理的地方 給一個@Transactional的註解就能夠。如圖所示:其中的配置文件在()中補充。
因爲時間緣由:後面兩種不經常使用的下回再補充。