真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網站制作重慶分公司

Spring@Transactional工作原理詳解

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

網站建設哪家好,找成都創(chuàng)新互聯(lián)!專注于網頁設計、網站建設、微信開發(fā)、重慶小程序開發(fā)、集團企業(yè)網站建設等服務項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了黃島免費建站歡迎大家使用!

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

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

JPA和事務管理

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

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

這種方式的事務管理使事務范圍可以在代碼中很清晰地表達出來,但它有以下缺點:

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

任何錯誤可能產生較大的影響

錯誤難以調試和復現(xiàn)

降低了代碼庫的可讀性

如果該方法調用了其他的事務方法如何處理呢?

使用Spring @Transactional

使用Spring @Transactional,上面的代碼就簡化為:

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

代碼更加簡潔,可讀性更好,也是目前Spring中事務處理的推薦方式。

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

這個強大機制的一個潛在缺點是它隱藏了底層的運行,當它不能正常工作時很難調試。

@Transactional含義

關于@Transactional,關鍵點之一是要考慮兩個獨立的概念,它們都有各自的范圍和生命周期:

persistence context(持久化上下文)

database transaction(事務)

@Transactional本身定義了單個事務的范圍。這個事務在persistence context的范圍內。

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

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

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

EntityManager何時跨越多個事務?

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

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

另一種情況是開發(fā)人員將持久化上下文標記為PersistenceContextType.EXTENDED,這表示它能夠響應多個請求。

如何定義EntityManager和Transaction之間的關系?

這由應用開發(fā)者來選擇,但是JPA Entity Manager最常用的方式是“Entity Manager per application transaction”(每個事務都有自己的實體管理器)模式。entity manager注入的常用方法是:

@PersistenceContext 
  privateEntityManager em; 

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

@PersistenceContext如何工作?

隨之而來的問題就是@PersistenceContext如何僅在容器啟動時注入entity manager,假定entity manager生命周期很短暫,而且每次請求需要多個entity manager。

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

通常用于代理的具體類為SharedEntityManagerInvocationHandler,借助調試器可以確認這一點。

那么@Transactional如何工作?

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

EntityManager Proxy本身

事務的切面

事務管理器

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

事務的切面

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

事務的切面有兩個主要職責:

在'before'時,切面提供一個調用點,來決定被調用業(yè)務方法應該在正在進行事務的范圍內運行,還是開始一個新的獨立事務。

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

在'before'時,事務切面自身不包含任何決策邏輯,是否開始新事務的決策委派給事務管理器完成。

事務管理器

事務管理器需要解決下面兩個問題:

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

是否應該開始新的事務?

這些需要事務切面'before'邏輯被調用時決定。事務管理器的決策基于以下兩點:

事務是否正在進行

事務方法的propagation屬性(比如REQUIRES_NEW總要開始新事務)

如果事務管理器確定要創(chuàng)建新事務,那么將:

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

2.entity manager綁定到當前線程

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

4.將連接綁定到當前線程

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

事務運行時他們存儲在線程中,當它們不再被使用時,事務管理器決定是否將他們清除。

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

EntityManager proxy

EntityManager proxy(前面已經介紹過)就是謎題的最后一部分。當業(yè)務方法調用entityManager.persist()時,這不是由entity manager直接調用的。

而是業(yè)務方法調用代理,代理從線程獲取當前的entity manager,前面介紹過事務管理器將entity manager綁定到線程。

了解了@Transactional機制的各個部分,我們來看一下實現(xiàn)它的常用Spring配置。

整合三個部分

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

這樣就可以通過持久化上下文注解注入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;
	}
}

下一步實現(xiàn)配置事務管理器和在@Transactional注解的類中應用事務的切面。

@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注解的類被事務的切面包圍。這樣@Transactional就可以使用了。

總結

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

當這個機制不能正常工作或者未達到預期運行結果等問題出現(xiàn)時,理解它的內部工作情況是很有幫助的。

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

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


本文標題:Spring@Transactional工作原理詳解
本文鏈接:http://weahome.cn/article/gejijd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部