spring的事務詳解

如果不想看概念的話,直接跳到編程式事務管理(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的註解










發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章