Spring事務(wù)管理的全解析
事務(wù)支持
什么是事務(wù)?
在一個(gè)業(yè)務(wù)流程中,需要多條DML(insert、delete、update)語(yǔ)句聯(lián)合才能完成。這些語(yǔ)句必須同時(shí)成功或者同時(shí)失敗。這樣才能保證數(shù)據(jù)安全。
多條DML同時(shí)成功或者同時(shí)失敗,叫做事務(wù)。
事務(wù)處理的四個(gè)過(guò)程
- 開啟事務(wù)
- 執(zhí)行業(yè)務(wù)代碼
- 提交事務(wù)(沒(méi)出現(xiàn)異常,提交成功。commit transaction)
- 回滾事務(wù)(出現(xiàn)異常。執(zhí)行回滾事務(wù). rollback transaction)
事務(wù)的四個(gè)特性(ACID)
- A原子性:事務(wù)是最小的工作單元,不可分
- C一致性:事務(wù)要么同時(shí)成功,要么同時(shí)失敗
- I隔離性:事務(wù)與事務(wù)之間保證和互不干擾
- D持久性:持久性是事務(wù)結(jié)束的標(biāo)志。
spring對(duì)事務(wù)的支持
spring實(shí)現(xiàn)事務(wù)的2種方式:
- 編程式事務(wù):通過(guò)編寫代碼的方式來(lái)實(shí)現(xiàn)事務(wù)管理
- 聲明式事務(wù):基于注解方式和基于xml方式(推薦使用)
spring事務(wù)管理api
spring對(duì)事務(wù)的管理是基于aop實(shí)現(xiàn)的。所以spring專門針對(duì)事務(wù)開發(fā)了一套api,其核心接口如下:PlatformTransactionManager 接口。
聲明式事務(wù)基于注解方式實(shí)現(xiàn)
需要配置xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" >
<!-- 組件掃描-->
<context:component-scan base-package="com.ali" />
<!-- 配置數(shù)據(jù)源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="jdbc:mysql://localhost:3306/bank"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
</bean>
<!-- 配置jdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事務(wù)管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 開啟事務(wù)注解驅(qū)動(dòng)器,開啟事務(wù)注解,需要加上tx的命名空間-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>可以在類和方法上加@Transactional 開啟事務(wù)
- 加在類上表示這個(gè)類上的所有方法都開啟事務(wù)
- 加在方法方法上表示只有這個(gè)方法開啟事務(wù)
事務(wù)的傳播行為
什么是事務(wù)的傳播行為?
在service種有a()和b()2個(gè)方法,a()上有事務(wù),b()上也有事務(wù),當(dāng)a()在執(zhí)行過(guò)程中調(diào)用了b(),事務(wù)是如何傳遞的?是合并到一個(gè)事務(wù)?還是開啟一個(gè)新事務(wù)?這就是事務(wù)的傳播行為。
一共有7種傳播行為:
- REQUIRD:支持當(dāng)前事務(wù),如果不存在就新建一個(gè)事務(wù)(默認(rèn))【沒(méi)有就新建,有就加入】
- SUPPORTS:支持當(dāng)前事務(wù),如果當(dāng)前沒(méi)有事務(wù),就以非事務(wù)方式執(zhí)行【有就加入,沒(méi)有就不管了】
- MANDATORY:必須運(yùn)行在一個(gè)事務(wù)中,如果當(dāng)前沒(méi)有事務(wù)發(fā)生,將拋出異?!居芯图尤耄瑳](méi)有就拋異?!?/li>
- REQUIRES_NEW:開啟一個(gè)新事務(wù),如果一個(gè)事務(wù)已經(jīng)存在,則將這個(gè)存在的事務(wù)掛起【不管有沒(méi)有。直接開啟一個(gè)新事務(wù)。新事務(wù)和舊事務(wù)不存在嵌套關(guān)系,舊事務(wù)被掛起了】
- NOT_SUPPORTED:以非事務(wù)方式運(yùn)行。如果有事務(wù)。則掛起當(dāng)前事務(wù)【不支持事務(wù),存在就掛起】
- NEVER:以非事務(wù)方式運(yùn)行。如果有事務(wù)。則拋異?!静恢С质聞?wù),存在就拋異?!?/li>
- NESTED:如果當(dāng)前有一個(gè)事務(wù)在進(jìn)行中,則該方法應(yīng)當(dāng)運(yùn)行在一個(gè)嵌套事務(wù)中。被嵌套的事務(wù)可以獨(dú)立于外層事務(wù)進(jìn)行提交或回滾。如果外層事務(wù)不存在。行為就像REQUIRD一樣【有事務(wù)的話,就在這個(gè)事務(wù)里嵌套一個(gè)完全獨(dú)立的事務(wù),嵌套的事務(wù)可以獨(dú)立的提交和回滾。沒(méi)有事務(wù)就和REQUIRD一樣】
在代碼中設(shè)置事務(wù)的傳播行為:
@Transactional(propagation = Propagation.MANDATORY)
事務(wù)隔離級(jí)別
數(shù)據(jù)庫(kù)中讀取數(shù)據(jù)存在三大問(wèn)題:
- 臟讀:讀取到?jīng)]有提交到數(shù)據(jù)庫(kù)的數(shù)據(jù)
- 不可重復(fù)讀:在同一個(gè)事務(wù)中,第一次和第二次讀取的數(shù)據(jù)不一樣
- 幻讀:讀到的數(shù)據(jù)是假的()
事務(wù)的隔離級(jí)別有4個(gè):
- 讀未提交READ_UNCOMMITTED: 存在臟讀、不可重復(fù)讀、幻讀問(wèn)題
- 讀提交READ_COMMITTED:事務(wù)提交之后才讀到。存在不可重復(fù)讀、幻讀問(wèn)題
- 可重復(fù)讀REPEATABLE_READ:解決不可重復(fù)讀的問(wèn)題,存在幻讀問(wèn)題
- 序列化SERIALIZABLE:解決幻讀問(wèn)題,事務(wù)排隊(duì)執(zhí)行。不支持并發(fā)。
MySQL默認(rèn)可重復(fù)讀,Oracle默認(rèn)讀提交
僅在讀的事務(wù)中設(shè)置隔離級(jí)別就行,寫的事務(wù)沒(méi)必要設(shè)置
代碼中設(shè)置事務(wù)的隔離級(jí)別:
@Transactional(isolation = Isolation.DEFAULT)
事務(wù)超時(shí)
@Transactional(timeout = 10)
以上代碼設(shè)置事務(wù)超時(shí)時(shí)間為10s
表示超過(guò)10s,如果事務(wù)中所有的DML語(yǔ)句還沒(méi)有執(zhí)行完畢的話,最終結(jié)果會(huì)回滾。
默認(rèn)值-1,表示沒(méi)有時(shí)間限制。
事務(wù)的超時(shí)時(shí)間值得是哪段時(shí)間?
在當(dāng)前事務(wù)中,最后一條DML語(yǔ)句執(zhí)行之前的時(shí)間,如果最后一條DML語(yǔ)句后面有很多業(yè)務(wù)邏輯,這些業(yè)務(wù)代碼執(zhí)行的時(shí)間不被計(jì)入超時(shí)時(shí)間。
只讀事務(wù)
@Transactional(readOnly = true)
將當(dāng)前事務(wù)設(shè)為只讀事務(wù),在該事務(wù)中只允許執(zhí)行select 語(yǔ)句。
該特性的作用是:?jiǎn)?dòng)spring的優(yōu)化策略。提高select語(yǔ)句的執(zhí)行效率。
設(shè)置哪些異?;貪L事務(wù)
@Transactional(rollbackFor = RuntimeException.class)
表示發(fā)生RuntimeException異常或該異常的子類異常才回滾
設(shè)置哪些異常不回滾事務(wù)
@Transactional(noRollbackFor = NullPointerException.class)
表示發(fā)生NullPointerException異?;蛟摦惓5淖宇惒换貪L,其他異常才回滾
事務(wù)的全注解式開發(fā)
編寫配置類
@Configuration // 代替xml配置文件
@ComponentScan("com.ali") // 掃描com.ali包下的所有類
@EnableTransactionManagement // 開啟事務(wù)管理
public class Spring6Config {
// @Bean注解用于將方法的返回值注冊(cè)為Spring容器中的一個(gè)Bean
@Bean(name = "druidDataSource")
public DruidDataSource druidDataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUrl("jdbc:mysql://localhost:3306/spring6?useSSL=false&serverTimezone=UTC");
druidDataSource.setUsername("root");
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setPassword("123456");
return druidDataSource;
}
@Bean(name = "transactionManager")
public DataSourceTransactionManager transactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
@Bean(name = "jdbcTemplate")
// 該方法的參數(shù)DataSource dataSource會(huì)自動(dòng)從Spring容器中找到類型為DataSource的Bean并注入
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
}使用時(shí)和其他方式一樣。
到此這篇關(guān)于Spring事務(wù)管理的文章就介紹到這了,更多相關(guān)spring事務(wù)管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java?Spring事務(wù)管理超詳細(xì)指南
- Spring事務(wù)管理中@Transactional失效的8個(gè)常見(jiàn)場(chǎng)景與解決方案
- Spring聲明式事務(wù)管理從原理到實(shí)戰(zhàn)示例
- Spring如何使用AOP實(shí)現(xiàn)聲明式事務(wù)管理
- SpringBoot整合MongoDB實(shí)現(xiàn)事務(wù)管理
- SpringBoot中TransactionTemplate事務(wù)管理的實(shí)現(xiàn)
- Spring中的事務(wù)管理及實(shí)現(xiàn)方式解析
- Spring?JDBC使用步驟和事務(wù)管理
- Spring聲明式事務(wù)@Transactional注解實(shí)現(xiàn)元數(shù)據(jù)驅(qū)動(dòng)的事務(wù)管理
相關(guān)文章
Java實(shí)現(xiàn)批量操作Excel的示例詳解
在操作Excel的場(chǎng)景中,通常會(huì)有一些針對(duì)Excel的批量操作,以GcExcel為例,為大家詳細(xì)介紹一下Java是如何實(shí)現(xiàn)批量操作Excel的,需要的可以參考一下2023-07-07
MyBatis-Plus基于MyBatis封裝 BaseMapper的流程步驟
MyBatis-Plus作為 MyBatis 的增強(qiáng)框架,通過(guò) BaseMapper 提供了通用的 CRUD 操作,極大地提升了開發(fā)效率,為了更透徹地理解其封裝機(jī)制,本文將采用鏈路追蹤的思維,從開發(fā)者調(diào)用接口開始,分析其如何基于 MyBatis 完成對(duì) BaseMapper 的封裝,需要的朋友可以參考下2025-04-04
解析SpringBoot @EnableAutoConfiguration的使用
這篇文章主要介紹了解析SpringBoot @EnableAutoConfiguration的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09

