最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring的事務(wù)傳播屬性REQUIRED_NESTED原理

 更新時(shí)間:2023年05月15日 08:52:34   作者:morris131  
這篇文章主要介紹了spring的事務(wù)傳播屬性REQUIRED_NESTED原理,在spring中,要想使用事務(wù)中的回滾點(diǎn),可以使用傳播屬性NESTED,需要的朋友可以參考下

傳統(tǒng)事務(wù)中回滾點(diǎn)的使用

package com.morris.spring.demo.jdbc;
import java.sql.*;
/**
 * 傳統(tǒng)JDBC中回滾點(diǎn)的使用
 */
public class TraditionSavePointDemo {
	public static void main(String[] args) throws SQLException {
		String url = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&allowMultiQueries=true&characterEncoding=UTF-8&useFastDateParsing=false&zeroDateTimeBehavior=convertToNull";
		String username = "user";
		String password = "user";
		Connection connection = DriverManager.getConnection(url, username, password);
		connection.setAutoCommit(false); // 不自動(dòng)提交
		Savepoint one = connection.setSavepoint("one");
		Savepoint two = null;
		try {
			Statement statement = connection.createStatement();
			statement.execute("insert into t_good(good_name, price) values('iphone14', 9999)");
			statement.close();
			two = connection.setSavepoint("two");
		} catch (Exception e) {
			e.printStackTrace();
			connection.rollback(one); // 回滾事務(wù)
		}
		try {
			Statement statement = connection.createStatement();
			statement.execute("insert into t_good(good_name, price) values('iphone15', 9999)");
			statement.close();
			boolean flag = true;
			if(flag) {
				throw new RuntimeException("xxxx");
			}
		} catch (Exception e) {
			e.printStackTrace();
			connection.rollback(two); // 回滾事務(wù)
		}
		connection.commit();
	}
}

在一個(gè)事務(wù)中可以指定回滾事務(wù)到某一個(gè)階段,實(shí)現(xiàn)精確控制事務(wù)。

事務(wù)的傳播屬性NESTED

在spring中,要想使用事務(wù)中的回滾點(diǎn),可以使用傳播屬性NESTED。

com.morris.spring.service.TransactionService#addGoodAndArea

@Transactional(propagation = Propagation.REQUIRED)
public void addGoodAndArea() {
	System.out.println("------addGoodAndArea-------");
	goodService.addGood();
	areaService.addArea(0);
}

com.morris.spring.service.AreaServiceImpl#addArea

@Transactional(propagation = Propagation.NESTED)
@Override
public boolean addArea(int i) {
	int y = 1000000 / i;
	Area area = new Area();
	area.setAreaCode(y);
	area.setAreaName("shenzhen");
	return areaDao.insert(area);
}

com.morris.spring.service.GoodServiceImpl#addGood

@Transactional(propagation = Propagation.NESTED)
@Override
public boolean addGood() {
	Good good = new Good();
	good.setGoodName("iphone");
	good.setPrice(BigDecimal.valueOf(99999));
	return goodDao.insert(good);
}

運(yùn)行結(jié)果如下:

DEBUG DataSourceTransactionManager:384 - Creating new transaction with name [com.morris.spring.service.TransactionService.addGoodAndArea]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG DriverManagerDataSource:144 - Creating new JDBC DriverManager Connection to [jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&allowMultiQueries=true&characterEncoding=UTF-8&useFastDateParsing=false&zeroDateTimeBehavior=convertToNull]
DEBUG DataSourceTransactionManager:267 - Acquired Connection [com.mysql.cj.jdbc.ConnectionImpl@8ef162] for JDBC transaction
DEBUG DataSourceTransactionManager:285 - Switching JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@8ef162] to manual commit
------addGoodAndArea-------
DEBUG DataSourceTransactionManager:477 - Creating nested transaction with name [com.morris.spring.service.GoodServiceImpl.addGood]
DEBUG JdbcTemplate:860 - Executing prepared SQL update
DEBUG JdbcTemplate:609 - Executing prepared SQL statement [insert into t_good(good_name, price) values(?,?)]
DEBUG DataSourceTransactionManager:767 - Releasing transaction savepoint
DEBUG DataSourceTransactionManager:477 - Creating nested transaction with name [com.morris.spring.service.AreaServiceImpl.addArea]
DEBUG DataSourceTransactionManager:870 - Rolling back transaction to savepoint
DEBUG DataSourceTransactionManager:877 - Initiating transaction rollback
DEBUG DataSourceTransactionManager:347 - Rolling back JDBC transaction on Connection [com.mysql.cj.jdbc.ConnectionImpl@8ef162]
DEBUG DataSourceTransactionManager:392 - Releasing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@8ef162] after transaction
java.lang.ArithmeticException: / by zero
... ...

發(fā)現(xiàn)整個(gè)事務(wù)都已經(jīng)回滾了,按照回滾點(diǎn)的邏輯,addArea()方法拋出異常,不是應(yīng)該只回滾到addArea()前嗎,也就是addGood()應(yīng)該被提交,這是為什么呢?

如果我們將addArea()方法try catch起來,就能得到我們想要的結(jié)果,addGood()被提交,而addArea()回滾,這又是為什么呢?我們帶著這幾個(gè)問題來分析源碼。

addAreaAndGood()開啟事務(wù)

addAreaAndGood()開啟事務(wù),最外層方法使用傳播屬性PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED效果都一樣,都是開啟一個(gè)新的事務(wù)。

org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction

else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
		def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
		def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
	// 第一次進(jìn)來
	SuspendedResourcesHolder suspendedResources = suspend(null);
	if (debugEnabled) {
		logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
	}
	try {
		// 開啟新事務(wù)
		return startTransaction(def, transaction, debugEnabled, suspendedResources);
	}
	catch (RuntimeException | Error ex) {
		resume(null, suspendedResources);
		throw ex;
	}
}

addGood()獲得事務(wù)并創(chuàng)建回滾點(diǎn)

addGood()從ThreadLocal中獲得addAreaAndGood()創(chuàng)建的事務(wù),然后發(fā)現(xiàn)自己的傳播屬性為PROPAGATION_NESTED,就創(chuàng)建了一個(gè)回滾點(diǎn)。

org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
	if (!isNestedTransactionAllowed()) {
		throw new NestedTransactionNotSupportedException(
				"Transaction manager does not allow nested transactions by default - " +
				"specify 'nestedTransactionAllowed' property with value 'true'");
	}
	if (debugEnabled) {
		logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
	}
	if (useSavepointForNestedTransaction()) {
		// Create savepoint within existing Spring-managed transaction,
		// through the SavepointManager API implemented by TransactionStatus.
		// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
		DefaultTransactionStatus status =
				prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
		// 創(chuàng)建回滾點(diǎn)
		status.createAndHoldSavepoint();
		return status;
	}
	else {
		// Nested transaction through nested begin and commit/rollback calls.
		// Usually only for JTA: Spring synchronization might get activated here
		// in case of a pre-existing JTA transaction.
		return startTransaction(definition, transaction, debugEnabled, null);
	}
}

addGood()提交事務(wù)時(shí)釋放回滾點(diǎn)

addGood()并不會(huì)真正的提交事務(wù),因?yàn)槭聞?wù)并不是addGood()創(chuàng)建的,只是在提交時(shí)會(huì)將之前創(chuàng)建的回滾點(diǎn)釋放。

org.springframework.transaction.support.AbstractPlatformTransactionManager#processCommit

if (status.hasSavepoint()) {
	// NESTED的提交
	if (status.isDebug()) {
		logger.debug("Releasing transaction savepoint");
	}
	unexpectedRollback = status.isGlobalRollbackOnly();
	// 只是釋放回滾點(diǎn)
	status.releaseHeldSavepoint();
}

addArea()獲得事務(wù)并創(chuàng)建回滾點(diǎn)

流程與addGood()一致。

addArea()回滾事務(wù)釋放回滾點(diǎn)

addArea()發(fā)生異常,會(huì)執(zhí)行回滾事務(wù)的邏輯,并沒有真正的回滾事務(wù),因?yàn)槭聞?wù)并不是addArea()創(chuàng)建的,,只是將之前創(chuàng)建的回滾點(diǎn)釋放。 org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback

if (status.hasSavepoint()) {
	// 用于NESTED傳播機(jī)制,發(fā)生異常
	// 回滾至回滾點(diǎn)
	if (status.isDebug()) {
		logger.debug("Rolling back transaction to savepoint");
	}
	status.rollbackToHeldSavepoint();
}

addAreaAndGood()回滾這個(gè)事務(wù)

addArea()發(fā)生異常后繼續(xù)往外拋,addAreaAndGood()也會(huì)捕獲到異常,然后執(zhí)行回滾邏輯,這樣整個(gè)事務(wù)都回滾了。 org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback

else if (status.isNewTransaction()) {
	// 只有最外層的事務(wù)newTransaction=true
	if (status.isDebug()) {
		logger.debug("Initiating transaction rollback");
	}
	// 事務(wù)的回滾
	/**
	 * @see org.springframework.jdbc.datasource.DataSourceTransactionManager#doRollback(org.springframework.transaction.support.DefaultTransactionStatus)
	 */
	doRollback(status);
}

為什么將addArea()方法try catch起來,整個(gè)事務(wù)就不會(huì)回滾了呢?

因?yàn)閷ddArea()方法try catch起來后,addAreaAndGood()就會(huì)執(zhí)行提交事務(wù)的邏輯,這樣addGood()就被提交了。

到此這篇關(guān)于spring的事務(wù)傳播屬性REQUIRED_NESTED原理的文章就介紹到這了,更多相關(guān)spring REQUIRED_NESTED原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JavaSE中compare、compareTo的區(qū)別

    JavaSE中compare、compareTo的區(qū)別

    本文主要介紹了JavaSE中compare、compareTo的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • 為什么Java要把字符串設(shè)計(jì)成不可變的

    為什么Java要把字符串設(shè)計(jì)成不可變的

    為什么Java要把字符串設(shè)計(jì)成不可變的,這篇文章給出了Java字符串設(shè)計(jì)成不可變的原因,感興趣的小伙伴們可以參考一下
    2017-06-06
  • 微信js sdk invalid signature簽名錯(cuò)誤問題的解決方法分析

    微信js sdk invalid signature簽名錯(cuò)誤問題的解決方法分析

    這篇文章主要介紹了微信js sdk invalid signature簽名錯(cuò)誤問題的解決方法,結(jié)合實(shí)例形式分析了微信簽名錯(cuò)誤問題相關(guān)解決方法,需要的朋友可以參考下
    2019-04-04
  • Java簡(jiǎn)單實(shí)現(xiàn)SpringMVC+MyBatis分頁插件

    Java簡(jiǎn)單實(shí)現(xiàn)SpringMVC+MyBatis分頁插件

    自己最近搭建的一個(gè)SpringMVC+Mybatis的框架 屬于無實(shí)體類的框架 并實(shí)現(xiàn)了Myabtis的自動(dòng)分頁和總數(shù)查詢 只要傳入分頁參數(shù)便能自動(dòng)查詢總數(shù)和分頁 總數(shù)封裝在參數(shù)里面執(zhí)行查詢后可以直接從參數(shù)中獲取
    2015-09-09
  • MybatisPlus如何處理Mysql的json類型

    MybatisPlus如何處理Mysql的json類型

    這篇文章主要介紹了MybatisPlus如何處理Mysql的json類型,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • SpringBoot通過注解注入Bean的幾種方式解析

    SpringBoot通過注解注入Bean的幾種方式解析

    這篇文章主要為大家介紹了SpringBoot注入Bean的幾種方式示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-03-03
  • 使用JPA自定義id策略避免主鍵自增

    使用JPA自定義id策略避免主鍵自增

    這篇文章主要介紹了使用JPA自定義id策略避免主鍵自增問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Java基礎(chǔ)入門總結(jié)之序列化和反序列化

    Java基礎(chǔ)入門總結(jié)之序列化和反序列化

    序列化是一種對(duì)象持久化的手段,普遍應(yīng)用在網(wǎng)絡(luò)傳輸、RMI等場(chǎng)景中,下面這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)入門總結(jié)之序列化和反序列化的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • Java集合List和Map互轉(zhuǎn)的方法總結(jié)

    Java集合List和Map互轉(zhuǎn)的方法總結(jié)

    有時(shí)候我們需要將給定的List轉(zhuǎn)換為Map,或者M(jìn)ap轉(zhuǎn)換為L(zhǎng)ist,本文主要介紹了Java集合List和Map互轉(zhuǎn)的方法總結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • Java版的7種單例模式寫法示例

    Java版的7種單例模式寫法示例

    這篇文章主要給大家介紹了關(guān)于Java版的7種單例模式寫法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10

最新評(píng)論

田阳县| 眉山市| 海伦市| 泸水县| 勐海县| 五原县| 集安市| 雅安市| 崇文区| 梨树县| 常熟市| 繁昌县| 峡江县| 进贤县| 筠连县| 文山县| 彭阳县| 香港 | 湛江市| 翼城县| 台州市| 公主岭市| 龙南县| 门头沟区| 古交市| 庆阳市| 南投市| 六枝特区| 靖西县| 临漳县| 无极县| 昌宁县| 佛冈县| 交口县| 明光市| 江门市| 偏关县| 泰来县| 大埔县| 枣强县| 兴城市|