如果不想看概念的話,直接跳到編程式事務管理(ctrl+F)那裏開始
事務的四大特性:
原子性,一致性,隔離性,持久性
原子性是指事務是一個不可分割的工作單位,十五中的操作要麼都發生,要麼都不發生。
一致性是指事務前後數據的完整性必須保持一致。
隔離性是指多個用戶併發訪問數據庫時,一個用戶的食物不能被其他用戶的事務所幹擾,多個併發事務之間數據要相互隔離。
持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,即使數據庫發生故障也不應該對齊有任何影響。
Spring事務管理高層抽象主要包括3個接口
PlatformTransactionManager(事務管理器)
TransactionDefinition(事務定義信息[隔離,傳播,超時,只讀])
TransactionStatus(事務具體運行狀態)
PlatformTransactionManager接口實現:
Org.springframework.jdbc.datasource.DataSourceTransactionManager(使用spring jdbc或ibatis進行持久化數據時使用)
Org.springframework.orm.hibernate3.HibernateTransactionManager(使用Hibernate3.0版本進行持久化數據)
Org.springframework.orm.jpa.JpaTransactionManager(使用JPA進行持久化時使用)
Org.springframework.jdo.JdoTransactionManager(當持久化機制是Jdo時使用)
Org.springframework.transaction.jta.JtaTransationManager(使用一個JTA實現來管理事務,在一個事務跨越多個資源時必須使用)
如果不考慮隔離性,會引發安全問題:
髒讀,不可重複讀,幻讀
髒讀:一個事務讀取了另一個事務改寫但還未提交的數據,如果這些數據被回滾,則讀到的數據是無效的
不可重複讀:在同一事務中,多次讀取同一數據返回的結果有所不同
幻讀:一個事務讀取了幾行記錄後,另一個事務插入一些記錄,幻讀就發生了,再後來的查詢中,第一個事務就會發現有些原來沒有的記錄
事務隔離級別(四種)
Default(使用後端數據庫默認的隔離級別)
READ_UNCOMMITED(允許你讀取還未提交的改變了的數據。可能導致髒,幻,不可重複讀)
READ_COMMITTED(允許在併發事務已經提交後讀取,可防止髒讀,但幻讀和不可重複讀仍會發生)
REPEATABLE_READ(對相同字段的多次讀取是一致的,除非數據被事務本身改變。可防止髒,不可重複讀,但幻讀扔可能發生)
SERIALIZABLE(完全服從ACID的隔離級別,確保不發生髒,幻,不可重複讀,這在所有隔離級別中是最慢的,它是典型的通過完全鎖定在事務中涉及的數據表來完成的)
PS:
Mysql默認採用REPEATABLE_READ隔離級別
Oracle默認採用READ_COMMITTED隔離級別
事務的傳播行爲(七種):
PROPAGATION_REQUIRED(支持當前事務,如果不存在,就新建一個)
PROPAGATION_SUPPORTS(支持當前事務,如果不存在,就不使用事務)
PROPAGATION_MANDATORY(支持當前事務,如果不存在,拋出異常)
PROPAGATION_REQUIRES_NEW(如果有事務存在,掛起當前事務,創建一個新的事務)
PROPAGATION_NOT_SUPPORTED(以非事務方式運行,如果有事務存在,掛起當前事務)
PROPAGATION_NEVER(以非事務方式運行,如果有事務存在,跑出異常)
PROPAGATION_NESTED(如果當前事務存在,則嵌套事務執行)
Spring支持兩種方式事務管理
--編程式的事務管理(一種)
*在實際應用中很少使用
*通過TransactionTemplate手動管理事務
--使用XML配置聲明式事務(三種)
*開發中推薦使用(代碼入侵性最小)
*Spring的聲明式事務是通過AOP實現的
編程式的事務管理:
Spring文件配置
<!--配置事務管理器 -->
<bean id=”transactionManager” class=”org.springframework.jdbc.datasource.DataSourceTransactionMnager”>
<property name=”dataSource” ref=”dataSource”/>
</bean>
<!--配置事務管理的模板 -->
<bean id=”transactionTemplate” class=”org.springframework.transaction.support. TransactionTemplate”>
<property name=”transactionManager” ref=”transactionManager”/>
</bean>
<!--配置業務層類-->
<bean id=”accountService” class=”cn.muke.spring.demo1.AccountServiceImpl”>
<property name=”accountDao” ref=”accountDao”/>
<!--注入事務管理的模板 -->
<property name=”transactionTemplate” ref=”transactionTemplate”/>
</bean>
在業務實現類裏面(serviceimpl):
//注入事務管理的模板:
Private TransactionTemplate transactionTemplate;
Public void transfer(String out,String in,double money){
TransactionTemplate.execute(new TransactionCallbackWithoutResult(){
Protected void doInTransactionWithoutResult(TransactionStatus transactionStatus){
AccountDao.outMoney(out,money);
Int i=1/0;
AccountDao.inMoney(in,money);
}
});
}
執行這個方法會失敗,因爲1/0會錯誤所以會回滾
聲明式事務管理方式一:基於TransactionProxyFactoryBean的方式
Spring文件配置
<!--配置事務管理器 -->
<bean id=”transactionManager” class=”org.springframework.jdbc.datasource.DataSourceTransactionMnager”>
<property name=”dataSource” ref=”dataSource”/>
</bean>
<!--配置業務層的代理-->
<bean id=”accountServiceProxy”class=”org.springframework.transaction.interceptor.TransactionProxyFactoryBean”>
<!--配置目標對象-->
<property name=”target” ref=”accountService”/>
<!--注入事務管理器 -->
<property name=”transactionManager” ref=”transactionManager”/>
<!--注入事務屬性 -->
<property name=”transactionAttributes”>
<props>
<!--prop的格式:
*代表類中所有方法
*PROPAGATION :事務的傳播行爲
*ISOLATION:事務的隔離級別
*readOnly:只讀(不可以進行插入,修改刪除)
*-Exception:發生哪些異常回滾事務
*+Exception:發生哪些異常不回滾事務
-->
<prop key=”transfer”> PROPAGATION </prop>
</props>
</property>
</bean>
聲明式事務管理方式二:基於AspectJ的XML方式
Spring文件配置
<!--配置事務管理器 -->
<bean id=”transactionManager” class=”org.springframework.jdbc.datasource.DataSourceTransactionMnager”>
<property name=”dataSource” ref=”dataSource”/>
</bean>
<!--配置事務的通知:(事務的增強)-->
<tx:advice id=”txAdvice”transaction-manager=”transactionManager”>
<tx:attributes>
<!--
Propagation:事務傳播行爲
Isolation:事務隔離級別
Read-only:只讀
Rollback-for:發生哪些異常回滾
No-rollback-for:發生哪些異常不會滾
Timeout”過期信息
-->
<tx:method name=”transfer” propagation=”REQUIRED”/>
</tx:attributes>
</ tx:advice >
<!--配置切面-->
<aop:config>
<!--配置切入點-->
<aop:pointcut expression=”execution(* cn.muke.spring.demo3.AccountService+.*(..))” id=”pointcut1”>
<!--配置切面-->
<aop:advisor advice-ref=”txAdvice” pointcut-ref=”pointcut1”/>
</aop:config>
聲明式事務管理方式三:基於註解方式
Spring文件配置
<!--配置事務管理器 -->
<bean id=”transactionManager” class=”org.springframework.jdbc.datasource.DataSourceTransactionMnager”>
<property name=”dataSource” ref=”dataSource”/>
</bean>
<!--開啓註解事務 -->
<tx:annotation-driven transaction-manager=”transactionManager”/>
在業務實現類裏面(serviceimpl):
加上@Transactional即可
@Transactiona註解中的屬性
Propagation:事務的傳播行爲
Isolation:事務的隔離級別
ReadOnly:只讀
RollbackFor:發生哪些異常回滾
NoRollbackFor:發生哪些異常不回滾
例如:Transactiona(propagation=Propagation.REQUIRED,isolation=Isolation.Default)
總結:
--編程式的事務管理
*通過TransactionTemplate手動管理事務(很少使用)
--使用XML配置聲明式事務
*基於TransactionProxyFactoryBean的方式(很少使用)
*需要爲每個進行事務管理的類,配置一個TransactionProxyFactoryBean進行增強
*基於AspectJ的XML方式(經常使用)
*一旦配置好了,需要在類上加任何東西
*基於註解方式(經常使用)
*配置簡單。需要在業務類上添加一個@Transactiona的註解