日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
長文捋明白Spring事務(wù)!隔離性?傳播性?一網(wǎng)打盡!

事務(wù)的重要性不言而喻,Spring 對事務(wù)也提供了非常豐富的支持,各種支持的屬性應(yīng)有盡有。

然而很多小伙伴知道,這里有兩個屬性特別繞:

  • 隔離性
  • 傳播性

有多繞呢?松哥都一直懶得寫文章去總結(jié)。不過最近有小伙伴問到這個問題,剛好有空,就抽空總結(jié)一下,我不會干巴巴的和大家講概念,接下來的所有內(nèi)容,松哥都會通過具體的案例來和大家演示。

好啦,不廢話啦,請看大屏幕。

1. 什么是事務(wù)

數(shù)據(jù)庫事務(wù)是指作為單個邏輯工作單元執(zhí)行的一系列操作,這些操作要么一起成功,要么一起失敗,是一個不可分割的工作單元。

在我們?nèi)粘9ぷ髦校婕暗绞聞?wù)的場景非常多,一個 service 中往往需要調(diào)用不同的 dao 層方法,這些方法要么同時成功要么同時失敗,我們需要在 service 層確保這一點(diǎn)。

說到事務(wù)最典型的案例就是轉(zhuǎn)賬了:

張三要給李四轉(zhuǎn)賬 500 塊錢,這里涉及到兩個操作,從張三的賬戶上減去 500 塊錢,給李四的賬戶添加 500 塊錢,這兩個操作要么同時成功要么同時失敗,如何確保他們同時成功或者同時失敗呢?答案就是事務(wù)。

事務(wù)有四大特性(ACID):

  • 原子性(Atomicity):一個事務(wù)(transaction)中的所有操作,要么全部完成,要么全部不完成,不會結(jié)束在中間某個環(huán)節(jié)。事務(wù)在執(zhí)行過程中發(fā)生錯誤,會被回滾(Rollback)到事務(wù)開始前的狀態(tài),就像這個事務(wù)從來沒有執(zhí)行過一樣。即,事務(wù)不可分割、不可約簡。
  • 一致性(Consistency):在事務(wù)開始之前和事務(wù)結(jié)束以后,數(shù)據(jù)庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預(yù)設(shè)約束、觸發(fā)器、級聯(lián)回滾等。
  • 隔離性(Isolation):數(shù)據(jù)庫允許多個并發(fā)事務(wù)同時對其數(shù)據(jù)進(jìn)行讀寫和修改,隔離性可以防止多個事務(wù)并發(fā)執(zhí)行時由于交叉執(zhí)行而導(dǎo)致數(shù)據(jù)的不一致。事務(wù)隔離分為不同級別,包括未提交讀(Read Uncommitted)、提交讀(Read Committed)、可重復(fù)讀(Repeatable Read)和串行化(Serializable)。
  • 持久性(Durability):事務(wù)處理結(jié)束后,對數(shù)據(jù)的修改就是永久的,即便系統(tǒng)故障也不會丟失。

這就是事務(wù)的四大特性。

2. Spring 中的事務(wù)

2.1 兩種用法

Spring 作為 Java 開發(fā)中的基礎(chǔ)設(shè)施,對于事務(wù)也提供了很好的支持,總體上來說,Spring 支持兩種類型的事務(wù),聲明式事務(wù)和編程式事務(wù)。

編程式事務(wù)類似于 Jdbc 事務(wù)的寫法,需要將事務(wù)的代碼嵌入到業(yè)務(wù)邏輯中,這樣代碼的耦合度較高,而聲明式事務(wù)通過 AOP 的思想能夠有效的將事務(wù)和業(yè)務(wù)邏輯代碼解耦,因此在實(shí)際開發(fā)中,聲明式事務(wù)得到了廣泛的應(yīng)用,而編程式事務(wù)則較少使用,考慮到文章內(nèi)容的完整,本文對兩種事務(wù)方式都會介紹。

2.2 三大基礎(chǔ)設(shè)施

Spring 中對事務(wù)的支持提供了三大基礎(chǔ)設(shè)施,我們先來了解下。

  • PlatformTransactionManager
  • TransactionDefinition
  • TransactionStatus

這三個核心類是 Spring 處理事務(wù)的核心類。

2.2.1 PlatformTransactionManager

PlatformTransactionManager 是事務(wù)處理的核心,它有諸多的實(shí)現(xiàn)類,如下:

PlatformTransactionManager 的定義如下:

public interface PlatformTransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition definition);
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}

可以看到 PlatformTransactionManager 中定義了基本的事務(wù)操作方法,這些事務(wù)操作方法都是平臺無關(guān)的,具體的實(shí)現(xiàn)都是由不同的子類來實(shí)現(xiàn)的。

這就像 JDBC 一樣,SUN 公司制定標(biāo)準(zhǔn),其他數(shù)據(jù)庫廠商提供具體的實(shí)現(xiàn)。這么做的好處就是我們 Java 程序員只需要掌握好這套標(biāo)準(zhǔn)即可,不用去管接口的具體實(shí)現(xiàn)。以 PlatformTransactionManager 為例,它有眾多實(shí)現(xiàn),如果你使用的是 JDBC 那么可以將 DataSourceTransactionManager 作為事務(wù)管理器;如果你使用的是 Hibernate,那么可以將 HibernateTransactionManager 作為事務(wù)管理器;如果你使用的是 JPA,那么可以將 JpaTransactionManager 作為事務(wù)管理器。DataSourceTransactionManager、HibernateTransactionManager 以及 JpaTransactionManager 都是 PlatformTransactionManager 的具體實(shí)現(xiàn),但是我們并不需要掌握這些具體實(shí)現(xiàn)類的用法,我們只需要掌握好 PlatformTransactionManager 的用法即可。

PlatformTransactionManager 中主要有如下三個方法:

(1)getTransaction()

getTransaction() 是根據(jù)傳入的 TransactionDefinition 獲取一個事務(wù)對象,TransactionDefinition 中定義了一些事務(wù)的基本規(guī)則,例如傳播性、隔離級別等。

(2)commit()

commit() 方法用來提交事務(wù)。

(3)rollback()

rollback() 方法用來回滾事務(wù)。

2.2.2 TransactionDefinition

TransactionDefinition 用來描述事務(wù)的具體規(guī)則,也稱作事務(wù)的屬性。事務(wù)有哪些屬性呢?看下圖:

可以看到,主要是五種屬性:

  • 隔離性
  • 傳播性
  • 回滾規(guī)則
  • 超時時間
  • 是否只讀

這五種屬性接下來松哥會和大家詳細(xì)介紹。

TransactionDefinition 類中的方法如下:

可以看到一共有五個方法:

  • getIsolationLevel(),獲取事務(wù)的隔離級別
  • getName(),獲取事務(wù)的名稱
  • getPropagationBehavior(),獲取事務(wù)的傳播性
  • getTimeout(),獲取事務(wù)的超時時間
  • isReadOnly(),獲取事務(wù)是否是只讀事務(wù)

TransactionDefinition 也有諸多的實(shí)現(xiàn)類,如下:

如果開發(fā)者使用了編程式事務(wù)的話,直接使用 DefaultTransactionDefinition 即可。

2.2.3 TransactionStatus

TransactionStatus 可以直接理解為事務(wù)本身,該接口源碼如下:

public interface TransactionStatus extends SavepointManager, Flushable {
boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
void flush();
boolean isCompleted();
}
  • isNewTransaction() 方法獲取當(dāng)前事務(wù)是否是一個新事務(wù)。
  • hasSavepoint() 方法判斷是否存在 savePoint()。
  • setRollbackOnly() 方法設(shè)置事務(wù)必須回滾。
  • isRollbackOnly() 方法獲取事務(wù)只能回滾。
  • flush() 方法將底層會話中的修改刷新到數(shù)據(jù)庫,一般用于 Hibernate/JPA 的會話,對如 JDBC 類型的事務(wù)無任何影響。
  • isCompleted() 方法用來獲取是一個事務(wù)是否結(jié)束。

這就是 Spring 中支持事務(wù)的三大基礎(chǔ)設(shè)施。

3. 編程式事務(wù)

我們先來看看編程式事務(wù)怎么玩。

通過 PlatformTransactionManager 或者 TransactionTemplate 可以實(shí)現(xiàn)編程式事務(wù)。如果是在 Spring Boot 項(xiàng)目中,這兩個對象 Spring Boot 會自動提供,我們直接使用即可。但是如果是在傳統(tǒng)的 SSM 項(xiàng)目中,則需要我們通過配置來提供這兩個對象,松哥給一個簡單的配置參考,如下(簡單起見,數(shù)據(jù)庫操作我們使用 JdbcTemplate):















有了這兩個對象,接下來的代碼就簡單了:

@Service
public class TransferService {
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
PlatformTransactionManager txManager;

public void transfer() {
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
TransactionStatus status = txManager.getTransaction(definition);
try {
jdbcTemplate.update("update user set account=account+100 where username='zhangsan'");
int i = 1 / 0;
jdbcTemplate.update("update user set account=account-100 where username='lisi'");
txManager.commit(status);
} catch (DataAccessException e) {
e.printStackTrace();
txManager.rollback(status);
}
}
}

這段代碼很簡單,沒啥好解釋的,在 try...catch... 中進(jìn)行業(yè)務(wù)操作,沒問題就 commit,有問題就 rollback。如果我們需要配置事務(wù)的隔離性、傳播性等,可以在 DefaultTransactionDefinition 對象中進(jìn)行配置。

上面的代碼是通過 PlatformTransactionManager 實(shí)現(xiàn)的編程式事務(wù),我們也可以通過 TransactionTemplate 來實(shí)現(xiàn)編程式事務(wù),如下:

@Service
public class TransferService {
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
TransactionTemplate tranTemplate;
public void transfer() {
tranTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
jdbcTemplate.update("update user set account=account+100 where username='zhangsan'");
int i = 1 / 0;
jdbcTemplate.update("update user set account=account-100 where username='lisi'");
} catch (DataAccessException e) {
status.setRollbackOnly();
e.printStackTrace();
}
}
});
}
}

直接注入 TransactionTemplate,然后在 execute 方法中添加回調(diào)寫核心的業(yè)務(wù)即可,當(dāng)拋出異常時,將當(dāng)前事務(wù)標(biāo)注為只能回滾即可。注意,execute 方法中,如果不需要獲取事務(wù)執(zhí)行的結(jié)果,則直接使用 TransactionCallbackWithoutResult 類即可,如果要獲取事務(wù)執(zhí)行結(jié)果,則使用 TransactionCallback 即可。

這就是兩種編程式事務(wù)的玩法。

編程式事務(wù)由于代碼入侵太嚴(yán)重了,因?yàn)樵趯?shí)際開發(fā)中使用的很少,我們在項(xiàng)目中更多的是使用聲明式事務(wù)。

4. 聲明式事務(wù)

聲明式事務(wù)如果使用 XML 配置,可以做到無侵入;如果使用 Java 配置,也只有一個 @Transactional 注解侵入而已,相對來說非常容易。

以下配置針對傳統(tǒng) SSM 項(xiàng)目(因?yàn)樵?Spring Boot 項(xiàng)目中,事務(wù)相關(guān)的組件已經(jīng)配置好了):

4.1 XML 配置

XML 配置聲明式事務(wù)大致上可以分為三個步驟,如下:

配置事務(wù)管理器









配置事務(wù)通知






配置 AOP




第二步和第三步中定義出來的方法交集,就是我們要添加事務(wù)的方法。

配置完成后,如下一些方法就自動具備事務(wù)了:

public class UserService {
public void m3(){
jdbcTemplate.update("update user set money=997 where username=?", "zhangsan");
}
}

4.2 Java 配置

我們也可以使用 Java 配置來實(shí)現(xiàn)聲明式事務(wù):

@Configuration
@ComponentScan
//開啟事務(wù)注解支持
@EnableTransactionManagement
public class JavaConfig {
@Bean
DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setPassword("123");
ds.setUsername("root");
ds.setUrl("jdbc:mysql:///test01?serverTimezone=Asia/Shanghai");
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
return ds;
}

@Bean
JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}

@Bean
PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}

這里要配置的東西其實(shí)和 XML 中配置的都差不多,最最關(guān)鍵的就兩個:

  • 事務(wù)管理器 PlatformTransactionManager。
  • @EnableTransactionManagement 注解開啟事務(wù)支持。

配置完成后,接下來,哪個方法需要事務(wù)就在哪個方法上添加 @Transactional 注解即可,向下面這樣:

@Transactional(noRollbackFor = ArithmeticException.class)
public void update4() {
jdbcTemplate.update("update account set money = ? where username=?;", 998, "lisi");
int i = 1 / 0;
}

當(dāng)然這個稍微有點(diǎn)代碼入侵,不過問題不大,日常開發(fā)中這種方式使用較多。當(dāng)@Transactional 注解加在類上面的時候,表示該類的所有方法都有事務(wù),該注解加在方法上面的時候,表示該方法有事務(wù)。

4.3 混合配置

也可以 Java 代碼和 XML 混合配置來實(shí)現(xiàn)聲明式事務(wù),就是一部分配置用 XML 來實(shí)現(xiàn),一部分配置用 Java 代碼來實(shí)現(xiàn):

假設(shè) XML 配置如下:


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/tx http://www.springframework.org/schema/tx/spring-tx.xsd">




那么 Java 代碼中的配置如下:

@Configuration
@ComponentScan
@ImportResource(locations = "classpath:applicationContext3.xml")
public class JavaConfig {
@Bean
DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setPassword("123");
ds.setUsername("root");
ds.setUrl("jdbc:mysql:///test01?serverTimezone=Asia/Shanghai");
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
return ds;
}

@Bean
JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}

@Bean
PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}

Java 配置中通過 @ImportResource 注解導(dǎo)入了 XML 配置,XML 配置中的內(nèi)容就是開啟 @Transactional 注解的支持,所以 Java 配置中省略了 @EnableTransactionManagement 注解。

這就是聲明式事務(wù)的幾種配置方式。好玩吧!

5. 事務(wù)屬性

在前面的配置中,我們只是簡單說了事務(wù)的用法,并沒有和大家詳細(xì)聊一聊事務(wù)的一些屬性細(xì)節(jié),那么接下來我們就來仔細(xì)捋一捋事務(wù)中的五大屬性。

5.1 隔離性

首先就是事務(wù)的隔離性,也就是事務(wù)的隔離級別。

MySQL 中有四種不同的隔離級別,這四種不同的隔離級別在 Spring 中都得到了很好的支持。Spring 中默認(rèn)的事務(wù)隔離級別是 default,即數(shù)據(jù)庫本身的隔離級別是啥就是啥,default 就能滿足我們?nèi)粘i_發(fā)中的大部分場景。

不過如果項(xiàng)目有需要,我們也可以調(diào)整事務(wù)的隔離級別。

調(diào)整方式如下:

5.1.1 編程式事務(wù)隔離級別

如果是編程式事務(wù),通過如下方式修改事務(wù)的隔離級別:

TransactionTemplate

transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);

TransactionDefinition 中定義了各種隔離級別。

PlatformTransactionManager

public void update2() {
//創(chuàng)建事務(wù)的默認(rèn)配置
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
TransactionStatus status = platformTransactionManager.getTransaction(definition);
try {
jdbcTemplate.update("update account set money = ? where username=?;", 999, "zhangsan");
int i = 1 / 0;
//提交事務(wù)
platformTransactionManager.commit(status);
} catch (DataAccessException e) {
e.printStackTrace();
//回滾
platformTransactionManager.rollback(status);
}
}

這里是在 DefaultTransactionDefinition 對象中設(shè)置事務(wù)的隔離級別。

5.1.2 聲明式事務(wù)隔離級別

如果是聲明式事務(wù)通過如下方式修改隔離級別:

XML:







Java:

@Transactional(isolation = Isolation.SERIALIZABLE)
public void update4() {
jdbcTemplate.update("update account set money = ? where username=?;", 998, "lisi");
int i = 1 / 0;
}

5.2 傳播性

先來說說何謂事務(wù)的傳播性:

事務(wù)傳播行為是為了解決業(yè)務(wù)層方法之間互相調(diào)用的事務(wù)問題,當(dāng)一個事務(wù)方法被另一個事務(wù)方法調(diào)用時,事務(wù)該以何種狀態(tài)存在?例如新方法可能繼續(xù)在現(xiàn)有事務(wù)中運(yùn)行,也可能開啟一個新事務(wù),并在自己的事務(wù)中運(yùn)行,等等,這些規(guī)則就涉及到事務(wù)的傳播性。

關(guān)于事務(wù)的傳播性,Spring 主要定義了如下幾種:

public enum Propagation {
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
NEVER(TransactionDefinition.PROPAGATION_NEVER),
NESTED(TransactionDefinition.PROPAGATION_NESTED);
private final int value;
Propagation(int value) { this.value = value; }
public int value() { return this.value; }
}

具體含義如下:

傳播性

描述

REQUIRED

如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個新的事務(wù)

SUPPORTS

如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行

MANDATORY

如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則拋出異常

REQUIRES_NEW

創(chuàng)建一個新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起

NOT_SUPPORTED

以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起

NEVER

以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常

NESTED

如果當(dāng)前存在事務(wù),則創(chuàng)建一個事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來運(yùn)行;如果當(dāng)前沒有事務(wù),則該取值等價于 TransactionDefinition.PROPAGATION_REQUIRED

一共是七種傳播性,具體配置也簡單:

TransactionTemplate中的配置

transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

PlatformTransactionManager中的配置

public void update2() {
//創(chuàng)建事務(wù)的默認(rèn)配置
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = platformTransactionManager.getTransaction(definition);
try {
jdbcTemplate.update("update account set money = ? where username=?;", 999, "zhangsan");
int i = 1 / 0;
//提交事務(wù)
platformTransactionManager.commit(status);
} catch (DataAccessException e) {
e.printStackTrace();
//回滾
platformTransactionManager.rollback(status);
}
}

聲明式事務(wù)的配置(XML)







聲明式事務(wù)的配置(Java)

@Transactional(noRollbackFor = ArithmeticException.class,propagation = Propagation.REQUIRED)
public void update4() {
jdbcTemplate.update("update account set money = ? where username=?;", 998, "lisi");
int i = 1 / 0;
}

用就是這么來用,至于七種傳播的具體含義,松哥來和大家一個一個說。

5.2.1 REQUIRED

REQUIRED 表示如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個新的事務(wù)。

例如我有如下一段代碼:

@Service
public class AccountService {
@Autowired
JdbcTemplate jdbcTemplate;
@Transactional
public void handle1() {
jdbcTemplate.update("update user set money = ? where id=?;", 1, 2);
}
}
@Service
public class AccountService2 {
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
AccountService accountService;
public void handle2() {
jdbcTemplate.update("update user set money = ? where username=?;", 1, "zhangsan");
accountService.handle1();
}
}

我在 handle2 方法中調(diào)用 handle1。

那么:

  • 如果 handle2 方法本身是有事務(wù)的,則 handle1 方法就會加入到 handle2 方法所在的事務(wù)中,這樣兩個方法將處于同一個事務(wù)中,一起成功或者一起失?。ú还苁?handle2 還是 handle1 誰拋異常,都會導(dǎo)致整體回滾)。
  • 如果 handle2 方法本身是沒有事務(wù)的,則 handle1 方法就會自己開啟一個新的事務(wù),自己玩。

舉一個簡單的例子:handle2 方法有事務(wù),handle1 方法也有事務(wù)(小伙伴們根據(jù)前面的講解自行配置事務(wù)),項(xiàng)目打印出來的事務(wù)日志如下:

o.s.jdbc.support.JdbcTransactionManager  : Creating new transaction with name [org.javaboy.spring_tran02.AccountService2.handle2]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
o.s.jdbc.support.JdbcTransactionManager : Acquired Connection [HikariProxyConnection@875256468 wrapping com.mysql.cj.jdbc.ConnectionImpl@9753d50] for JDBC transaction
o.s.jdbc.support.JdbcTransactionManager : Switching JDBC Connection [HikariProxyConnection@875256468 wrapping com.mysql.cj.jdbc.ConnectionImpl@9753d50] to manual commit
o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [update user set money = ? where username=?;]
o.s.jdbc.support.JdbcTransactionManager : Participating in existing transaction
o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [update user set money = ? where id=?;]
o.s.jdbc.support.JdbcTransactionManager : Initiating transaction commit
o.s.jdbc.support.JdbcTransactionManager : Committing JDBC transaction on Connection [HikariProxyConnection@875256468 wrapping com.mysql.cj.jdbc.ConnectionImpl@9753d50]
o.s.jdbc.support.JdbcTransactionManager : Releasing JDBC Connection [HikariProxyConnection@875256468 wrapping com.mysql.cj.jdbc.ConnectionImpl@9753d50] after transaction

從日志中可以看到,前前后后一共就開啟了一個事務(wù),日志中有這么一句:

Participating in existing transaction

這個就說明 handle1 方法沒有自己開啟事務(wù),而是加入到 handle2 方法的事務(wù)中了。

5.2.2 REQUIRES_NEW

REQUIRES_NEW 表示創(chuàng)建一個新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。換言之,不管外部方法是否有事務(wù),REQUIRES_NEW 都會開啟自己的事務(wù)。

這塊松哥要多說兩句,有的小伙伴可能覺得 REQUIRES_NEW 和 REQUIRED 太像了,似乎沒啥區(qū)別。其實(shí)你要是單純看最終回滾效果,可能確實(shí)看不到啥區(qū)別。但是,大家注意松哥上面的加粗,在 REQUIRES_NEW 中可能會同時存在兩個事務(wù),外部方法的事務(wù)被掛起,內(nèi)部方法的事務(wù)獨(dú)自運(yùn)行,而在 REQUIRED 中則不會出現(xiàn)這種情況,如果內(nèi)外部方法傳播性都是 REQUIRED,那么最終也只是一個事務(wù)。

還是上面那個例子,假設(shè) handle1 和 handle2 方法都有事務(wù),handle2 方法的事務(wù)傳播性是 REQUIRED,而 handle1 方法的事務(wù)傳播性是 REQUIRES_NEW,那么最終打印出來的事務(wù)日志如下:

o.s.jdbc.support.JdbcTransactionManager  : Creating new transaction with name [org.javaboy.spring_tran02.AccountService2.handle2]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
o.s.jdbc.support.JdbcTransaction
本文題目:長文捋明白Spring事務(wù)!隔離性?傳播性?一網(wǎng)打盡!
網(wǎng)頁路徑:http://m.5511xx.com/article/dpphpjs.html