1. 程式人生 > 實用技巧 >如何通過 Spring 框架進行 JDBC 事務控制呢?

如何通過 Spring 框架進行 JDBC 事務控制呢?

如何通過 Spring 框架進行 JDBC 事務控制呢?

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-P6EkyKAL-1600675538236)(https://imgkr.cn-bj.ufileos.com/50416f44-5b7e-43bb-a0c4-ee71be577c04.jpg)]

Spring 進行 JDBC 事務控制的方式

  • 通過 xml 配置實現
  • 通過註解實現

案例實操

Xml 事物配置宣告

1).修改 xml 名稱空間

xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx 
http://www.springframework.org/schema/tx/spring-tx.xsd

2).aop代理

<aop:aspectj-autoproxy /><!-- aop -->

3).配置事物管理器

<!-- 事務管理器定義 -->
<bean id="txManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"></property>
</bean>

4).配置事務相關通知

一般來說增刪改方法

propagation=Required,對於查詢方法使用 read-only="true"

示例如下:

<!-- 配置通知 -->
<!--
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 將觸發事務回滾
-->
<tx:advice id="txAdvice" transaction-manager="txManager">
	<tx:attributes>
	<!--匹配以 save 開頭的 service 方法均加入事務-->
	<tx:method name="save*" propagation="REQUIRED" />
	<!—匹配以 del 開頭的 service 方法均加入事務-->
	<tx:method name="del*" propagation="REQUIRED" />
    <!—匹配以 update 開頭的 service 方法均加入事務-->
	<tx:method name="update*" propagation="REQUIRED" />
	<!—匹配以 query 開頭的 service 方法事物為只讀模式-->
	<tx:method name="query*" read-only="true" />
	</tx:attributes>
</tx:advice>
事務傳播行為介紹
@Transactional(propagation=Propagation.REQUIRED) 
如果有事務, 那麼加入事務, 沒有的話新建一個(預設情況下)
@Transactional(propagation=Propagation.NOT_SUPPORTED) 
容器不為這個方法開啟事務
@Transactional(propagation=Propagation.REQUIRES_NEW) 
不管是否存在事務,都建立一個新的事務,原來的掛起,新的執行完畢,繼續執行老的事務
@Transactional(propagation=Propagation.MANDATORY) 
必須在一個已有的事務中執行,否則丟擲異常
@Transactional(propagation=Propagation.NEVER) 
必須在一個沒有的事務中執行,否則丟擲異常(與 Propagation.MANDATORY 相反)
@Transactional(propagation=Propagation.SUPPORTS) 
如果其他 bean 呼叫這個方法,在其他 bean 中宣告事務,那就用事務.如果其他 bean 沒有宣告事務,那就不用事務.

5).配置 aop(切入點、通知)

<!-- aop 切面定義 -->
<aop:config>
    <aop:pointcut expression="execution( * com.xxx.service..*.*(..) )"id="cut" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="cut" />
</aop:config>

Spring 事務管理註解方式

1).配置事物管理器

<!-- spring 註解式事務宣告 -->
<!-- 事務管理器定義 -->
<bean id="txManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

2).配置註解支援

<tx:annotation-driven transaction-manager="txManager"/>

3).Service 方法上在需要新增事務的方法上加入事物註解

@Override
@Transactional(propagation=Propagation.REQUIRED)
public void saveUser(String userName,String userPwd){
    User user1=new User();
    user1.setUserName(userName);
    user1.setUserPwd(userPwd);
    userDao.saveUser(user1);
    userDao.delUserById(2);
}

備註:預設 spring 事務只在發生未被捕獲的 runtimeexcetpion 時才回滾。spring aop 異常捕獲原理:被攔截的方法需顯式丟擲異常,並不能經任何處理,這樣 aop 代理才能捕獲到方法的異常,才能進行回滾,預設情況下 aop 只捕獲runtimeexception 的異常,但可以通過配置來捕獲特定的異常並回滾 換句話說在service 的方法中不使用 try catch 或者在 catch 中最後加上 throw new RunTimeexcetpion(),這樣程式異常時才能被 aop 捕獲進而回滾.

擴充套件

事務四大特性(即:ACID)

原子性(Atomicity):業務控制的最小單位,併發控制的最小單位,【不可以分割】

一致性(Consistency):事務在執行前後,資料庫中資料要保持一致性狀態。(如轉賬的過程 賬戶操作後資料必須保持一致)---- > 保證資料的完整性(正確性)

隔離性(Isolation):事務與事務之間的執行應當是相互隔離互不影響的。(多個角色對統一記錄進行操作必須保證沒有任何干擾),當然沒有影響是不可能的,為了讓影響級別降到最低,通過隔離級別加以限制:

  • READ_UNCOMMITTED
  • READ_COMMITTED
  • REPEATABLE_READ
  • SERIALIZABLE

務與事務之間的執行應當是相互隔離互不影響的。(多個角色對統一記錄進行操作必須保證沒有任何干擾),當然沒有影響是不可能的,為了讓影響級別降到最低,通過隔離級別加以限制:

  • READ_UNCOMMITTED
  • READ_COMMITTED
  • REPEATABLE_READ
  • SERIALIZABLE

永續性(Durability):事務提交完畢後,資料庫中的資料的改變是永久的.