如何通過 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).配置事務相關通知
一般來說增刪改方法
示例如下:
<!-- 配置通知 --> <!-- 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):事務提交完畢後,資料庫中的資料的改變是永久的.