javascript
(九)Spring 事务开发、事务属性详解
持久層
目錄
- 事務(wù)回顧
- Spring 控制事務(wù)的開發(fā)
- Spring 中的事務(wù)屬性(Transaction Attribute)
- 隔離屬性(ISOLATION)
- 傳播屬性(PROPAGATION)
- 只讀屬性(readOnly)
- 超時屬性(timeout)
- 異常屬性
- 事務(wù)屬性常見配置總結(jié)
- 基于標簽的事務(wù)配置方式
?
事務(wù)回顧
什么是事務(wù)?
- 事務(wù)時保證業(yè)務(wù)操作完整性的一種數(shù)據(jù)庫機制。
事務(wù)的 4 大特點:?A、C、I、D
- A?原子性
- C?一致性
- I?隔離性
- D?持久性
如何控制事務(wù)?(JDBC、Mybatis)
JDBC
- Connection.setAutoCommit(false);
- Connection.commit();
- Connection.rollback();
Mybatis
- Mybatis 自動開啟事務(wù)
- sqlSession.commit();,底層還是調(diào)用的?Connection
- sqlSession.rollback();,底層還是調(diào)用的?Connection
結(jié)論:控制事務(wù)的底層,都是通過?Connection?對象完成的。
Spring 控制事務(wù)的開發(fā)
- 搭建開發(fā)環(huán)境?pom.xml
- 編碼
- 細節(jié)
進行動態(tài)代理底層實現(xiàn)的切換,默認?false?是 JDK,true?是 Cglib。
Spring 中的事務(wù)屬性(Transaction Attribute)
什么是事務(wù)屬性?
屬性:描述物體特征的一系列值(性別、身高、體重)
事務(wù)屬性:描述事務(wù)特征的一系列值
如何添加事務(wù)屬性?
@Transactional(isolation=, propagation=, readOnly=,timeout=,rollbackFor,noRollbackFor=,)隔離屬性(ISOLATION)
概念:描述了事務(wù)解決并發(fā)問題的特征。
多個事務(wù)(用戶)在同一時間,訪問操作了相同的數(shù)據(jù)。
同一時間:0.000 幾秒左右
- 臟讀
- 不可重復讀
- 幻影讀
通過隔離屬性解決,隔離屬性中設(shè)置不同過的值,解決并發(fā)處理的過程中的問題。
事務(wù)并發(fā)產(chǎn)生的問題:
- 臟讀
一個事務(wù),讀取了另一個事務(wù)中沒有提交的數(shù)據(jù),會在本事務(wù)中產(chǎn)生數(shù)據(jù)不一樣的現(xiàn)象
解決方案:@Transaction(isolation=Isolation.READ_COMMITTED) - 不可重復讀
一個事務(wù)中,多次讀取相同的數(shù)據(jù),但是讀取結(jié)果不一樣,會在本事務(wù)中產(chǎn)生數(shù)據(jù)不一樣的現(xiàn)象
注意:1.不是臟讀 2.在一個事務(wù)中
解決方案:@Transaction(isolation=Isolation.REPEATABLE_READ)
本質(zhì):一把行鎖(對數(shù)據(jù)庫表的某一行加鎖) - 幻影讀
一個事務(wù)中,多次對整表進行查詢統(tǒng)計,但是結(jié)果不一樣,會在本事務(wù)中產(chǎn)生數(shù)據(jù)不一致的問題
解決方案:@Transaction(isolation=Isolation.SERIALIZABLE)
本質(zhì):表鎖(對數(shù)據(jù)庫某個表加鎖)
安全與效率對比:
- 并發(fā)安全:SERIALIZABLE?>?READ_ONLY?>?READ_COMMITTED
- 運行效率:READ_COMMITTED?>?READ_ONLY?>?SERIALIZABLE
數(shù)據(jù)庫對隔離屬性的支持:
| ISOLATION_READ_COMMITTED | 支持 | 支持 |
| ISOLATION_REPEATABLE_READ | 支持 | 不支持 |
| ISOLATION_SERIALIZABLE | 支持 | 支持hi |
- Oracle 不支持?REPEATABLE_READ,那該如何解決不可重復讀?
采用?多版本比對?的方式解決不可重復讀問題。
默認的隔離屬性:
- Spring 會指定為?ISOLATION_DEFAULT,調(diào)用不同數(shù)據(jù)庫所設(shè)置的默認隔離屬性
MySQL:REPEATABLE_READ
Oracle:READ_COMMITTED - 查看數(shù)據(jù)庫的默認隔離屬性:
MySQL:SELECT @@tx_isolation;
Oracle:較麻煩,建議百度。
隔離屬性在實驗中的建議:
- 推薦使用 Spring 默認指定的?ISOLATION_DEFAULT
- 未來的實戰(zhàn)中,遇到并發(fā)訪問的情況,很少見
- 如果真的遇到并發(fā)問題,解決方案:樂觀鎖
Hibernate(JPA):version
MyBatis:通過攔截器自定義開發(fā)
傳播屬性(PROPAGATION)
概念:描述了事務(wù)解決?嵌套 問題?的特征。
事務(wù)的嵌套:指的是一個大的事務(wù)中,包含了若干個小的事務(wù)。
事務(wù)嵌套產(chǎn)生的問題: 大事務(wù)中融入了很多小的事務(wù),他們彼此影響,最終就導致外部大的事務(wù)喪失了事務(wù)的原子性。
傳播屬性的值及其用法:
| REQUIRED | 開啟新的事務(wù) | 融合到外部事務(wù)中 | @Transactional(propagation = Propagation.REQUIRED) | 增、刪、改方法 |
| SUPPORTS | 不開啟事務(wù) | 融合到外部事務(wù)中 | @Transactional(propagation = Propagation.SUPPORTS) | 查詢方法 |
| REQUIRES_NEW | 開啟新的事務(wù) | 掛起外部事務(wù),創(chuàng)建新的事務(wù) | @Transactional(propagation = Propagation.REQUIRES_NEW) | 日志記錄方法中 |
| NOT_SUPPORTED | 不開啟事務(wù) | 掛起外部事務(wù) | @Transactional(propagation = Propagation.NOT_SUPPORTED) | 極其不常用 |
| NEVER | 不開啟事務(wù) | 拋出異常 | @Transactional(propagation = Propagation.NEVER) | 極其不常用 |
| MANDATORY | 拋出異常 | 融合到外部事物中 | @Transactional(propagation = Propagation.MANDATORY) | 極其不常用 |
Spring 中傳播屬性的默認值是:REQUIRED
推薦傳播屬性的使用方式:
- 增刪改 方法:使用默認值 REQUIRED
- 查詢 方法:顯示指定傳播屬性的值為 SUPPORTS
只讀屬性(readOnly)
針對于?只進行查詢操作的業(yè)務(wù)方法,可以加入只讀屬性,提高運行效率。
默認值:false
超時屬性(timeout)
指定了事務(wù)等待的最長時間。
當前事務(wù)訪問數(shù)據(jù)時,有可能訪問的數(shù)據(jù)被別的事務(wù)進行加鎖的處理,那么此時本事務(wù)就必須進行等待。
-1 表示超時屬性由對應的數(shù)據(jù)庫來指定(一般不會主動指定,-1 即可)
異常屬性
Spring 事務(wù)處理過程中:
- 默認對于?RuntimeException?及其子類,采用?回滾?的策略。
- 默認對于?Exception?及其子類,采用?提交?的策略。
使用方法:
@Transactional(rollbackFor = java.lang.Exception.class, xxx, xxx)@Transactional(noRollbackFor = java.lang.RuntimeException, xxx, xxx)建議:實戰(zhàn)中使用?RuntimeException?及其子類,使用事務(wù)異常屬性的默認值。
事務(wù)屬性常見配置總結(jié)
增刪改操作:@Transactional
查詢操作:@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
基于標簽的事務(wù)配置方式
基于注解?@Transaction?的事務(wù)配置回顧:
<bean id="userService" class="com.yusael.service.UserServiceImpl"><property name="userDAO" ref="userDAO"/> </bean><!--DataSourceTransactionManager--> <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/> </bean>@Transactional public class UserServiceImpl implements UserService {private UserDAO userDAO;<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>基于標簽的事務(wù)配置:
<!--DataSourceTransactionManager--> <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/> </bean><tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager"><tx:attributes><tx:method name="register" isolation="DEFAULT" propagation="REQUIRED"/></tx:attributes> </tx:advice><aop:config><aop:pointcut id="pc" expression="execution(* com.yusael.service.UserServiceImpl.register(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/> </aop:config>基于標簽的事務(wù)配置在?實戰(zhàn)?中的應用方式:
<tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager"><tx:attributes><tx:method name="register"/><tx:method name="modify*"/>編程時候, service中負責進行增刪改操作的方法 都以 modify 開頭查詢操作 命名無所謂<tx:method name="*" propagation="SUPPORTS" read-only="true"/></tx:attributes> </tx:advice><aop:config><aop:pointcut id="pc" expression="execution(* com.yusael.service..*.*(..))"/>應用的過程中, 將 service 都放到 service 包下<aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/> </aop:config> 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的(九)Spring 事务开发、事务属性详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 100元最强电脑配置?
- 下一篇: Temok将你的在线状态提升到一个新的水