Spring 進(jìn)行 JDBC 事務(wù)控制的方式
通過 xml 配置實(shí)現(xiàn)
通過注解實(shí)現(xiàn)
案例實(shí)操
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).配置事物管理器
<!-- 事務(wù)管理器定義 -->
<beanid="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
? ? <propertyname="dataSource"ref="dataSource"></property>
</bean>
4).配置事務(wù)相關(guān)通知
一般來說增刪改方法 propagation=Required,對(duì)于查詢方法使用 read-only="true"
示例如下:
<!-- 配置通知 -->
<!--
tx:method 的屬性:
* name 是必須的,表示與事務(wù)屬性關(guān)聯(lián)的方法名(業(yè)務(wù)方法名),對(duì)切入點(diǎn)進(jìn)行細(xì)化棺禾。通配
符(*)可以用來指定一批關(guān)聯(lián)到相同的事務(wù)屬性的方法桦山。
如:'get*'螺戳、'handle*'秕岛、'on*Event'等等.
propagation 不是必須的 碌燕,默認(rèn)值是 REQUIRED
表示事務(wù)傳播行為, 包括
REQUIRED,SUPPORTS,MANDATORY,REQUIRES_NEW,NOT_SUPPORTED,NEVER,NESTED
isolation 不是必須的 默認(rèn)值 DEFAULT
表示事務(wù)隔離級(jí)別(數(shù)據(jù)庫(kù)的隔離級(jí)別)
timeout 不是必須的 默認(rèn)值-1(永不超時(shí))
表示事務(wù)超時(shí)的時(shí)間(以秒為單位)
read-only 不是必須的 默認(rèn)值 false 不是只讀的
表示事務(wù)是否只讀
rollback-for 不是必須的
表示將被觸發(fā)進(jìn)行回滾的 Exception(s);以逗號(hào)分開继薛。
如:'com.foo.MyBusinessException,ServletException'
no-rollback-for 不是必須的
表示不被觸發(fā)進(jìn)行回滾的 Exception(s)陆蟆;以逗號(hào)分開。
如:'com.foo.MyBusinessException,ServletException'
任何 RuntimeException 將觸發(fā)事務(wù)回滾
-->
<tx:adviceid="txAdvice"transaction-manager="txManager">
? ? <tx:attributes>
? ? <!--匹配以 save 開頭的 service 方法均加入事務(wù)-->
? ? <tx:methodname="save*"propagation="REQUIRED"/>
? ? <tx:methodname="del*"propagation="REQUIRED"/>
?? <!—匹配以 update 開頭的 service 方法均加入事務(wù)-->
? ? <tx:methodname="update*"propagation="REQUIRED"/>
? ? <tx:methodname="query*"read-only="true"/>
? ? </tx:attributes>
</tx:advice>
事務(wù)傳播行為介紹
@Transactional(propagation=Propagation.REQUIRED)
如果有事務(wù), 那么加入事務(wù), 沒有的話新建一個(gè)(默認(rèn)情況下)
@Transactional(propagation=Propagation.NOT_SUPPORTED)
容器不為這個(gè)方法開啟事務(wù)
@Transactional(propagation=Propagation.REQUIRES_NEW)
不管是否存在事務(wù),都創(chuàng)建一個(gè)新的事務(wù),原來的掛起,新的執(zhí)行完畢,繼續(xù)執(zhí)行老的事務(wù)
@Transactional(propagation=Propagation.MANDATORY)
必須在一個(gè)已有的事務(wù)中執(zhí)行,否則拋出異常
@Transactional(propagation=Propagation.NEVER)
必須在一個(gè)沒有的事務(wù)中執(zhí)行,否則拋出異常(與 Propagation.MANDATORY 相反)
@Transactional(propagation=Propagation.SUPPORTS)
如果其他 bean 調(diào)用這個(gè)方法,在其他 bean 中聲明事務(wù),那就用事務(wù).如果其他 bean 沒有聲明事務(wù),那就不用事務(wù).
5).配置 aop(切入點(diǎn)惋增、通知)
<!-- aop 切面定義 -->
<aop:config>
<aop:pointcutexpression="execution( * com.xxx.service..*.*(..) )"id="cut"/>
<aop:advisoradvice-ref="txAdvice"pointcut-ref="cut"/>
</aop:config>
Spring 事務(wù)管理注解方式
1).配置事物管理器
<!-- spring 注解式事務(wù)聲明 -->
<!-- 事務(wù)管理器定義 -->
<beanid="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<propertyname="dataSource"ref="dataSource"></property>
</bean>
2).配置注解支持
<tx:annotation-driventransaction-manager="txManager"/>
3).Service 方法上在需要添加事務(wù)的方法上加入事物注解
@Override
@Transactional(propagation=Propagation.REQUIRED)
publicvoidsaveUser(StringuserName,StringuserPwd){
Useruser1=newUser();
user1.setUserName(userName);
user1.setUserPwd(userPwd);
userDao.saveUser(user1);
userDao.delUserById(2);
}
備注:默認(rèn) spring 事務(wù)只在發(fā)生未被捕獲的 runtimeexcetpion 時(shí)才回滾。spring aop 異常捕獲原理:被攔截的方法需顯式拋出異常改鲫,并不能經(jīng)任何處理诈皿,這樣 aop 代理才能捕獲到方法的異常,才能進(jìn)行回滾像棘,默認(rèn)情況下 aop 只捕獲runtimeexception 的異常稽亏,但可以通過配置來捕獲特定的異常并回滾 換句話說在service 的方法中不使用 try catch 或者在 catch 中最后加上 throw new RunTimeexcetpion(),這樣程序異常時(shí)才能被 aop 捕獲進(jìn)而回滾.
擴(kuò)展
事務(wù)四大特性(即:ACID)
原子性(Atomicity):業(yè)務(wù)控制的最小單位缕题,并發(fā)控制的最小單位截歉,【不可以分割】
一致性(Consistency):事務(wù)在執(zhí)行前后,數(shù)據(jù)庫(kù)中數(shù)據(jù)要保持一致性狀態(tài)烟零。(如轉(zhuǎn)賬的過程 賬戶操作后數(shù)據(jù)必須保持一致)---- > 保證數(shù)據(jù)的完整性(正確性)
隔離性(Isolation):事務(wù)與事務(wù)之間的執(zhí)行應(yīng)當(dāng)是相互隔離互不影響的瘪松。(多個(gè)角色對(duì)統(tǒng)一記錄進(jìn)行操作必須保證沒有任何干擾)咸作,當(dāng)然沒有影響是不可能的,為了讓影響級(jí)別降到最低宵睦,通過隔離級(jí)別加以限制:
READ_UNCOMMITTED
READ_COMMITTED
REPEATABLE_READ
SERIALIZABLE
持久性(Durability):事務(wù)提交完畢后记罚,數(shù)據(jù)庫(kù)中的數(shù)據(jù)的改變是永久的.