精品熟女碰碰人人a久久,多姿,欧美欧美a v日韩中文字幕,日本福利片秋霞国产午夜,欧美成人禁片在线观看

spring的事務傳播屬性REQUIRED_NESTED的原理介紹

spring的事務傳播屬性required_nested的原理介紹

本文講解"spring的事務傳播屬性required_nested的原理介紹",希望能夠解決相關問題。

傳統事務中回滾點的使用

package?com.morris.spring.demo.jdbc;
import?java.sql.*;
/**
?*?傳統jdbc中回滾點的使用
?*/
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);?//?不自動提交
		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);?//?回滾事務
		}
		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);?//?回滾事務
		}
		connection.commit();
	}
}

在一個事務中可以指定回滾事務到某一個階段,實現精確控制事務。

事務的傳播屬性nested

在spring中,要想使用事務中的回滾點,可以使用傳播屬性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);
}

運行結果如下:

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
...?...

發現整個事務都已經回滾了,按照回滾點的邏輯,addarea()方法拋出異常,不是應該只回滾到addarea()前嗎,也就是addgood()應該被提交,這是為什么呢?

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

addareaandgood()開啟事務

addareaandgood()開啟事務,最外層方法使用傳播屬性propagation_required、propagation_requires_new、propagation_nested效果都一樣,都是開啟一個新的事務。

org.springframework.transaction.support.abstractplatformtransactionmanager#gettransaction

else?if?(def.getpropagationbehavior()?==?transactiondefinition.propagation_required?||
		def.getpropagationbehavior()?==?transactiondefinition.propagation_requires_new?||
		def.getpropagationbehavior()?==?transactiondefinition.propagation_nested)?{
	//?第一次進來
	suspendedresourcesholder?suspendedresources?=?suspend(null);
	if?(debugenabled)?{
		logger.debug("creating?new?transaction?with?name?["?+?def.getname()?+?"]:?"?+?def);
	}
	try?{
		//?開啟新事務
		return?starttransaction(def,?transaction,?debugenabled,?suspendedresources);
	}
	catch?(runtimeexception?|?error?ex)?{
		resume(null,?suspendedresources);
		throw?ex;
	}
}

addgood()獲得事務并創建回滾點

addgood()從threadlocal中獲得addareaandgood()創建的事務,然后發現自己的傳播屬性為propagation_nested,就創建了一個回滾點。

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);
		//?創建回滾點
		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()提交事務時釋放回滾點

addgood()并不會真正的提交事務,因為事務并不是addgood()創建的,只是在提交時會將之前創建的回滾點釋放。

org.springframework.transaction.support.abstractplatformtransactionmanager#processcommit

if?(status.hassavepoint())?{
	//?nested的提交
	if?(status.isdebug())?{
		logger.debug("releasing?transaction?savepoint");
	}
	unexpectedrollback?=?status.isglobalrollbackonly();
	//?只是釋放回滾點
	status.releaseheldsavepoint();
}

addarea()獲得事務并創建回滾點

流程與addgood()一致。

addarea()回滾事務釋放回滾點

addarea()發生異常,會執行回滾事務的邏輯,并沒有真正的回滾事務,因為事務并不是addarea()創建的,,只是將之前創建的回滾點釋放。 org.springframework.transaction.support.abstractplatformtransactionmanager#processrollback

if?(status.hassavepoint())?{
	//?用于nested傳播機制,發生異常
	//?回滾至回滾點
	if?(status.isdebug())?{
		logger.debug("rolling?back?transaction?to?savepoint");
	}
	status.rollbacktoheldsavepoint();
}

addareaandgood()回滾這個事務

addarea()發生異常后繼續往外拋,addareaandgood()也會捕獲到異常,然后執行回滾邏輯,這樣整個事務都回滾了。 org.springframework.transaction.support.abstractplatformtransactionmanager#processrollback

else?if?(status.isnewtransaction())?{
	//?只有最外層的事務newtransaction=true
	if?(status.isdebug())?{
		logger.debug("initiating?transaction?rollback");
	}
	//?事務的回滾
	/**
	?*?@see?org.springframework.jdbc.datasource.datasourcetransactionmanager#dorollback(org.springframework.transaction.support.defaulttransactionstatus)
	?*/
	dorollback(status);
}

為什么將addarea()方法try catch起來,整個事務就不會回滾了呢?

因為將addarea()方法try catch起來后,addareaandgood()就會執行提交事務的邏輯,這樣addgood()就被提交了。

關于 "spring的事務傳播屬性required_nested的原理介紹" 就介紹到此。希望多多支持碩編程

下一節:解決springboot全局異常處理與aop日志處理中@afterthrowing失效問題的方法

java編程技術

相關文章