欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring @Transactional工作原理詳解

 更新時(shí)間:2017年12月29日 15:41:18   作者:Haiyoung  
這篇文章主要介紹了Spring @Transactional工作原理詳解,具有一定借鑒價(jià)值,需要的朋友可以參考下。

本文將深入研究Spring的事務(wù)管理。主要介紹@Transactional在底層是如何工作的。之后的文章將介紹:

propagation(事務(wù)傳播)和isolation(隔離性)等屬性的使用

事務(wù)使用的陷阱有哪些以及如何避免

JPA和事務(wù)管理

很重要的一點(diǎn)是JPA本身并不提供任何類(lèi)型的聲明式事務(wù)管理。如果在依賴(lài)注入容器之外使用JPA,事務(wù)處理必須由開(kāi)發(fā)人員編程實(shí)現(xiàn)。

UserTransaction utx = entityManager.getTransaction();
try{
	utx.begin();
	businessLogic();
	utx.commit();
}
catch(Exception ex) {
	utx.rollback();
	throwex;
}

這種方式的事務(wù)管理使事務(wù)范圍可以在代碼中很清晰地表達(dá)出來(lái),但它有以下缺點(diǎn):

容易出現(xiàn)重復(fù)代碼和錯(cuò)誤

任何錯(cuò)誤可能產(chǎn)生較大的影響

錯(cuò)誤難以調(diào)試和復(fù)現(xiàn)

降低了代碼庫(kù)的可讀性

如果該方法調(diào)用了其他的事務(wù)方法如何處理呢?

使用Spring @Transactional

使用Spring @Transactional,上面的代碼就簡(jiǎn)化為:

@Transactional 
  publicvoid businessLogic() { 
    ... use entity manager inside a transaction ... 
  } 

代碼更加簡(jiǎn)潔,可讀性更好,也是目前Spring中事務(wù)處理的推薦方式。

通過(guò)使用@Transactional,事務(wù)傳播等很多重要方面可以自動(dòng)處理。這種情況下如果businessLogic()調(diào)用了其他事務(wù)方法,該方法將根據(jù)選項(xiàng)確定如何加入正在運(yùn)行事務(wù)。

這個(gè)強(qiáng)大機(jī)制的一個(gè)潛在缺點(diǎn)是它隱藏了底層的運(yùn)行,當(dāng)它不能正常工作時(shí)很難調(diào)試。

@Transactional含義

關(guān)于@Transactional,關(guān)鍵點(diǎn)之一是要考慮兩個(gè)獨(dú)立的概念,它們都有各自的范圍和生命周期:

persistence context(持久化上下文)

database transaction(事務(wù))

@Transactional本身定義了單個(gè)事務(wù)的范圍。這個(gè)事務(wù)在persistence context的范圍內(nèi)。

JPA中的持久化上下文是EntityManager,內(nèi)部實(shí)現(xiàn)使用了Hibernate Session(使用Hibernate作為持久化provider)。

持久化上下文僅僅是一個(gè)同步對(duì)象,它記錄了有限集合的Java對(duì)象的狀態(tài),并且保證這些對(duì)象的變化最終持久化到數(shù)據(jù)庫(kù)。

這是與單個(gè)事務(wù)非常不同的概念。一個(gè)Entity Manager可以跨越多個(gè)事務(wù)使用,而且的確是這樣使用的。

EntityManager何時(shí)跨越多個(gè)事務(wù)?

最常見(jiàn)的情況是應(yīng)用使用Open Session In View模式處理懶初始化異常時(shí),之前的文章介紹過(guò)這種做法的優(yōu)勢(shì)和劣勢(shì)。

這種情況下視圖層運(yùn)行的多個(gè)查詢(xún)處于獨(dú)立的事務(wù)中,而不是單事務(wù)的業(yè)務(wù)邏輯,但這些查詢(xún)由相同的entity manager管理。

另一種情況是開(kāi)發(fā)人員將持久化上下文標(biāo)記為PersistenceContextType.EXTENDED,這表示它能夠響應(yīng)多個(gè)請(qǐng)求。

如何定義EntityManager和Transaction之間的關(guān)系?

這由應(yīng)用開(kāi)發(fā)者來(lái)選擇,但是JPA Entity Manager最常用的方式是“Entity Manager per application transaction”(每個(gè)事務(wù)都有自己的實(shí)體管理器)模式。entity manager注入的常用方法是:

@PersistenceContext 
  privateEntityManager em; 

這里默認(rèn)為“Entity Manager per transaction”模式。這種模式下如果在@Transactional方法內(nèi)部使用該Entity Manager,那么該方法將在單一事務(wù)中運(yùn)行。

@PersistenceContext如何工作?

隨之而來(lái)的問(wèn)題就是@PersistenceContext如何僅在容器啟動(dòng)時(shí)注入entity manager,假定entity manager生命周期很短暫,而且每次請(qǐng)求需要多個(gè)entity manager。

答案是它不能:EntityManager是一個(gè)接口,注入到spring bean中的不是entity manager本身,而是在運(yùn)行時(shí)代理具體entity manager的context aware proxy(上下文感知代理)。

通常用于代理的具體類(lèi)為SharedEntityManagerInvocationHandler,借助調(diào)試器可以確認(rèn)這一點(diǎn)。

那么@Transactional如何工作?

實(shí)現(xiàn)了EntityManager接口的持久化上下文代理并不是聲明式事務(wù)管理的唯一部分,事實(shí)上包含三個(gè)組成部分:

EntityManager Proxy本身

事務(wù)的切面

事務(wù)管理器

看一下這三部分以及它們之間的相互作用。

事務(wù)的切面

事務(wù)的切面是一個(gè)“around(環(huán)繞)”切面,在注解的業(yè)務(wù)方法前后都可以被調(diào)用。實(shí)現(xiàn)切面的具體類(lèi)是TransactionInterceptor。

事務(wù)的切面有兩個(gè)主要職責(zé):

在'before'時(shí),切面提供一個(gè)調(diào)用點(diǎn),來(lái)決定被調(diào)用業(yè)務(wù)方法應(yīng)該在正在進(jìn)行事務(wù)的范圍內(nèi)運(yùn)行,還是開(kāi)始一個(gè)新的獨(dú)立事務(wù)。

在'after'時(shí),切面需要確定事務(wù)被提交,回滾或者繼續(xù)運(yùn)行。

在'before'時(shí),事務(wù)切面自身不包含任何決策邏輯,是否開(kāi)始新事務(wù)的決策委派給事務(wù)管理器完成。

事務(wù)管理器

事務(wù)管理器需要解決下面兩個(gè)問(wèn)題:

新的Entity Manager是否應(yīng)該被創(chuàng)建?

是否應(yīng)該開(kāi)始新的事務(wù)?

這些需要事務(wù)切面'before'邏輯被調(diào)用時(shí)決定。事務(wù)管理器的決策基于以下兩點(diǎn):

事務(wù)是否正在進(jìn)行

事務(wù)方法的propagation屬性(比如REQUIRES_NEW總要開(kāi)始新事務(wù))

如果事務(wù)管理器確定要?jiǎng)?chuàng)建新事務(wù),那么將:

1.創(chuàng)建一個(gè)新的entity manager

2.entity manager綁定到當(dāng)前線程

3.從數(shù)據(jù)庫(kù)連接池中獲取連接

4.將連接綁定到當(dāng)前線程

使用ThreadLocal變量將entity manager和數(shù)據(jù)庫(kù)連接都綁定到當(dāng)前線程。

事務(wù)運(yùn)行時(shí)他們存儲(chǔ)在線程中,當(dāng)它們不再被使用時(shí),事務(wù)管理器決定是否將他們清除。

程序的任何部分如果需要當(dāng)前的entity manager和數(shù)據(jù)庫(kù)連接都可以從線程中獲取。

EntityManager proxy

EntityManager proxy(前面已經(jīng)介紹過(guò))就是謎題的最后一部分。當(dāng)業(yè)務(wù)方法調(diào)用entityManager.persist()時(shí),這不是由entity manager直接調(diào)用的。

而是業(yè)務(wù)方法調(diào)用代理,代理從線程獲取當(dāng)前的entity manager,前面介紹過(guò)事務(wù)管理器將entity manager綁定到線程。

了解了@Transactional機(jī)制的各個(gè)部分,我們來(lái)看一下實(shí)現(xiàn)它的常用Spring配置。

整合三個(gè)部分

如何將三個(gè)部分組合起來(lái)使事務(wù)注解可以正確地發(fā)揮作用呢?首先定義entity manager工廠。

這樣就可以通過(guò)持久化上下文注解注入Entity Manager proxy。

@Configuration 
  publicclass EntityManagerFactoriesConfiguration {
	@Autowired 
	    privateDataSource dataSource;
	@Bean(name = "entityManagerFactory") 
	    publicLocalContainerEntityManagerFactoryBean emf() {
		LocalContainerEntityManagerFactoryBean emf = ... 
		      emf.setDataSource(dataSource);
		emf.setPackagesToScan( 
		        newString[] {
			"your.package"
		}
		);
		emf.setJpaVendorAdapter( 
		        newHibernateJpaVendorAdapter());
		returnemf;
	}
}

下一步實(shí)現(xiàn)配置事務(wù)管理器和在@Transactional注解的類(lèi)中應(yīng)用事務(wù)的切面。

@Configuration 
  @EnableTransactionManagement 
  publicclass TransactionManagersConfig {
	@Autowired 
	    EntityManagerFactory emf;
	@Autowired 
	    privateDataSource dataSource;
	@Bean(name = "transactionManager") 
	    publicPlatformTransactionManager transactionManager() {
		JpaTransactionManager tm =  
		        newJpaTransactionManager();
		tm.setEntityManagerFactory(emf);
		tm.setDataSource(dataSource);
		returntm;
	}
}

注解@EnableTransactionManagement通知Spring,@Transactional注解的類(lèi)被事務(wù)的切面包圍。這樣@Transactional就可以使用了。

總結(jié)

Spring聲明式事務(wù)管理機(jī)制非常強(qiáng)大,但它可能被誤用或者容易發(fā)生配置錯(cuò)誤。

當(dāng)這個(gè)機(jī)制不能正常工作或者未達(dá)到預(yù)期運(yùn)行結(jié)果等問(wèn)題出現(xiàn)時(shí),理解它的內(nèi)部工作情況是很有幫助的。

需要記住的最重要的一點(diǎn)是,要考慮到兩個(gè)概念:事務(wù)和持久化上下文,每個(gè)都有自己不可讀的明顯的生命周期。

以上就是本文關(guān)于Spring @Transactional工作原理詳解的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專(zhuān)題,如有不足之處,歡迎留言指出。感謝朋友們對(duì)本站的支持!

相關(guān)文章

  • Java Socket+多線程實(shí)現(xiàn)多人聊天室功能

    Java Socket+多線程實(shí)現(xiàn)多人聊天室功能

    這篇文章主要為大家詳細(xì)介紹了Java Socket+多線程實(shí)現(xiàn)多人聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Java如何實(shí)現(xiàn)自定義異常類(lèi)

    Java如何實(shí)現(xiàn)自定義異常類(lèi)

    這篇文章主要介紹了Java如何實(shí)現(xiàn)自定義異常類(lèi),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • 全面解析Java main方法

    全面解析Java main方法

    main方法是我們學(xué)習(xí)Java語(yǔ)言學(xué)習(xí)的第一個(gè)方法,也是每個(gè)java使用者最熟悉的方法,每個(gè)Java應(yīng)用程序都必須有且僅有一個(gè)main方法。這篇文章通過(guò)實(shí)例代碼給大家介紹java main方法的相關(guān)知識(shí),感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧
    2018-05-05
  • spring-boot項(xiàng)目啟動(dòng)遲緩異常排查解決記錄

    spring-boot項(xiàng)目啟動(dòng)遲緩異常排查解決記錄

    這篇文章主要為大家介紹了spring-boot項(xiàng)目啟動(dòng)遲緩異常排查解決記錄,突然在本地啟動(dòng)不起來(lái)了,表象特征就是在本地IDEA上運(yùn)行時(shí),進(jìn)程卡住也不退出,應(yīng)用啟動(dòng)時(shí)加載相關(guān)組件的日志也不輸出
    2022-02-02
  • idea tomcat亂碼問(wèn)題的解決及相關(guān)設(shè)置的步驟

    idea tomcat亂碼問(wèn)題的解決及相關(guān)設(shè)置的步驟

    這篇文章主要介紹了idea tomcat亂碼問(wèn)題的解決及相關(guān)設(shè)置的步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • Java定時(shí)任務(wù)schedule和scheduleAtFixedRate的異同

    Java定時(shí)任務(wù)schedule和scheduleAtFixedRate的異同

    本文主要介紹了Java定時(shí)任務(wù)schedule和scheduleAtFixedRate的異同,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • SpringBoot中JPA實(shí)現(xiàn)Sort排序的三種方式小結(jié)

    SpringBoot中JPA實(shí)現(xiàn)Sort排序的三種方式小結(jié)

    這篇文章主要介紹了SpringBoot中JPA實(shí)現(xiàn)Sort排序的三種方式小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • SpringBoot_Cache自定義使用SimpleCacheManager方式

    SpringBoot_Cache自定義使用SimpleCacheManager方式

    這篇文章主要介紹了SpringBoot_Cache自定義使用SimpleCacheManager方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java解決浮點(diǎn)數(shù)計(jì)算不精確問(wèn)題的方法詳解

    Java解決浮點(diǎn)數(shù)計(jì)算不精確問(wèn)題的方法詳解

    在 Java 中,浮點(diǎn)數(shù)計(jì)算不精確問(wèn)題指的是使用浮點(diǎn)數(shù)進(jìn)行運(yùn)算時(shí),由于浮點(diǎn)數(shù)的內(nèi)部表示方式和十進(jìn)制數(shù)的表示方式存在差異,導(dǎo)致計(jì)算結(jié)果可能出現(xiàn)誤差,本文就給大家介紹一下Java如何解決浮點(diǎn)數(shù)計(jì)算不精確問(wèn)題,需要的朋友可以參考下
    2023-09-09
  • classloader類(lèi)加載器_基于java類(lèi)的加載方式詳解

    classloader類(lèi)加載器_基于java類(lèi)的加載方式詳解

    下面小編就為大家?guī)?lái)一篇classloader類(lèi)加載器_基于java類(lèi)的加載方式詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10

最新評(píng)論