日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring @Transactional实际如何工作?

發(fā)布時(shí)間:2023/12/3 javascript 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring @Transactional实际如何工作? 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在本文中,我們將深入探討Spring事務(wù)管理。 我們將討論@Transactional在@Transactional如何真正工作。 其他即將發(fā)布的帖子將包括:

  • 如何使用傳播和隔離等功能
  • 主要陷阱是什么以及如何避免它們

JPA和事務(wù)管理

重要的是要注意,JPA本身不提供任何類型的聲明式事務(wù)管理。 在依賴項(xiàng)注入容器之外使用JPA時(shí),開發(fā)人員需要以編程方式處理事務(wù):

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

這種管理事務(wù)的方式使代碼中的事務(wù)范圍非常清楚,但是有一些缺點(diǎn):

  • 它是重復(fù)性的并且容易出錯(cuò)
  • 任何錯(cuò)誤都會(huì)產(chǎn)生很大的影響
  • 錯(cuò)誤很難調(diào)試和重現(xiàn)
  • 這降低了代碼庫的可讀性
  • 如果此方法調(diào)用另一個(gè)事務(wù)方法怎么辦?

使用Spring @Transactional

使用Spring @Transactional ,上述代碼簡化為:

@Transactionalpublic void businessLogic() {... use entity manager inside a transaction ...}

這更加方便和易讀,是當(dāng)前在Spring中推薦的處理事務(wù)的推薦方法。

通過使用@Transactional ,可以自動(dòng)處理許多重要方面,例如事務(wù)傳播。 在這種情況下,如果businessLogic()調(diào)用了另一個(gè)事務(wù)方法,則該方法可以選擇加入正在進(jìn)行的事務(wù)。

潛在的不利之處在于,這種強(qiáng)大的機(jī)制隱藏了幕后發(fā)生的事情,從而在無法正常工作時(shí)很難進(jìn)行調(diào)試。

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

  • 持久性環(huán)境
  • 數(shù)據(jù)庫事務(wù)

事務(wù)注釋本身定義了單個(gè)數(shù)據(jù)庫事務(wù)的范圍。 數(shù)據(jù)庫事務(wù)在持久性上下文的范圍內(nèi)發(fā)生。

持久性上下文在JPA中是EntityManager ,使用Hibernate Session在內(nèi)部實(shí)現(xiàn)(當(dāng)使用Hibernate作為持久性提供程序時(shí))。

持久性上下文只是一個(gè)同步器對象,該對象跟蹤一組有限的Java對象的狀態(tài),并確保最終將這些對象上的更改持久化回到數(shù)據(jù)庫中。

這與數(shù)據(jù)庫事務(wù)的概念非常不同。 一個(gè)實(shí)體管理器可用于多個(gè)數(shù)據(jù)庫事務(wù) ,而實(shí)際上經(jīng)常是這樣。

EntityManager何時(shí)跨多個(gè)數(shù)據(jù)庫事務(wù)?

最常見的情況是,當(dāng)應(yīng)用程序使用“打開視圖中的會(huì)話”模式來處理延遲的初始化異常時(shí),請參見上一篇博客文章,以了解其優(yōu)缺點(diǎn) 。

在這種情況下,在視圖層中運(yùn)行的查詢與用于業(yè)務(wù)邏輯的查詢不在單獨(dú)的數(shù)據(jù)庫事務(wù)中,但是它們是通過同一實(shí)體管理器進(jìn)行的。

另一種情況是,開發(fā)人員將持久性上下文標(biāo)記為PersistenceContextType.EXTENDED ,這意味著它可以承受多個(gè)請求。

什么定義了EntityManager vs Transaction關(guān)系?

這實(shí)際上是應(yīng)用程序開發(fā)人員的選擇,但是使用JPA實(shí)體管理器的最常見方法是使用“每個(gè)應(yīng)用程序事務(wù)的實(shí)體管理器”模式。 這是注入實(shí)體管理器的最常見方法:

@PersistenceContextprivate EntityManager em;

在這里,默認(rèn)情況下,我們處于“每個(gè)事務(wù)實(shí)體管理器”模式。 在這種模式下,如果我們在@Transactional方法內(nèi)使用此實(shí)體管理器,則該方法將在單個(gè)數(shù)據(jù)庫事務(wù)中運(yùn)行。

@PersistenceContext如何工作?

想到的一個(gè)問題是,鑒于實(shí)體管理器的生命周期如此短,并且每個(gè)請求通常有多個(gè)實(shí)體,因此@PersistenceContext如何在容器啟動(dòng)時(shí)僅注入一次實(shí)體管理器。

答案是:它不能: EntityManager是一個(gè)接口,注入到bean中的不是實(shí)體管理器本身,而是上下文感知的代理 ,它將在運(yùn)行時(shí)委派給具體的實(shí)體管理器。

通常,用于代理的具體類是SharedEntityManagerInvocationHandler ,可以在調(diào)試器的幫助下進(jìn)行確認(rèn)。

@Transactional如何工作?

實(shí)現(xiàn)EntityManager的持久性上下文代理不是使聲明式事務(wù)管理工作所需的唯一組件。 實(shí)際上需要三個(gè)獨(dú)立的組件:

  • EntityManager代理本身
  • 交易方面
  • 交易經(jīng)理

讓我們逐一檢查一下,看看它們?nèi)绾蜗嗷プ饔谩?

交易方面

事務(wù)方面是在注釋的業(yè)務(wù)方法之前和之后都被調(diào)用的“周圍”方面。 實(shí)現(xiàn)方面的具體類是TransactionInterceptor 。

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

  • 在“之前”時(shí)刻,該方面提供了一個(gè)掛鉤點(diǎn),用于確定要調(diào)用的業(yè)務(wù)方法是否應(yīng)在正在進(jìn)行的數(shù)據(jù)庫事務(wù)范圍內(nèi)運(yùn)行,或者是否應(yīng)該啟動(dòng)新的單獨(dú)事務(wù)。
  • 在“之后”時(shí)刻,方面需要確定是應(yīng)該提交事務(wù),回滾事務(wù)還是保持運(yùn)行。

在“之前”時(shí)刻,事務(wù)方面本身不包含任何決策邏輯,如果需要,則啟動(dòng)新事務(wù)的決策將委托給事務(wù)管理器。

交易經(jīng)理

交易經(jīng)理需要提供以下兩個(gè)問題的答案:

  • 是否應(yīng)該創(chuàng)建一個(gè)新的實(shí)體管理器?
  • 是否應(yīng)該啟動(dòng)新的數(shù)據(jù)庫事務(wù)?

這需要在調(diào)用事務(wù)方面“之前”邏輯時(shí)確定。 交易經(jīng)理將根據(jù)以下內(nèi)容做出決定:

  • 一項(xiàng)交易是否已經(jīng)進(jìn)行的事實(shí)
  • 事務(wù)方法的傳播屬性(例如, REQUIRES_NEW始終啟動(dòng)新事務(wù))

如果交易經(jīng)理決定創(chuàng)建新交易,則它將:

  • 創(chuàng)建一個(gè)新的實(shí)體經(jīng)理
  • 將實(shí)體管理器綁定到當(dāng)前線程
  • 從數(shù)據(jù)庫連接池中獲取連接
  • 將連接綁定到當(dāng)前線程

實(shí)體管理器和連接都使用ThreadLocal變量綁定到當(dāng)前線程。

它們在事務(wù)運(yùn)行時(shí)存儲(chǔ)在線程中,并且當(dāng)不再需要它們時(shí),由事務(wù)管理器來清理它們。

程序中需要當(dāng)前實(shí)體管理器或連接的任何部分都可以從線程中檢索它們。 正是這樣做的一個(gè)程序組件是EntityManager代理。

EntityManager代理

最后一步是EntityManager代理(我們之前已經(jīng)介紹過)。 以業(yè)務(wù)方法為例
entityManager.persist() ,此調(diào)用未直接調(diào)用實(shí)體管理器。

相反,業(yè)務(wù)方法調(diào)用代理,該代理從線程(事務(wù)管理器放置在該線程中)中檢索當(dāng)前實(shí)體管理器。

現(xiàn)在知道了@Transactional機(jī)制的哪些移動(dòng)部分,讓我們@Transactional這項(xiàng)工作所需的常規(guī)Spring配置。

全部放在一起

讓我們研究一下如何設(shè)置使事務(wù)注釋正確工作所需的三個(gè)組件。 我們首先定義實(shí)體管理器工廠。

這將允許通過持久性上下文注釋注入Entity Manager代理:

@Configurationpublic class EntityManagerFactoriesConfiguration {@Autowiredprivate DataSource dataSource;@Bean(name = "entityManagerFactory")public LocalContainerEntityManagerFactoryBean emf() {LocalContainerEntityManagerFactoryBean emf = ...emf.setDataSource(dataSource);emf.setPackagesToScan(new String[] {"your.package"});emf.setJpaVendorAdapter(new HibernateJpaVendorAdapter());return emf;}}

下一步是配置事務(wù)管理器,并將事務(wù)方面應(yīng)用于@Transactional注釋的類:

@Configuration@EnableTransactionManagementpublic class TransactionManagersConfig {@AutowiredEntityManagerFactory emf;@Autowiredprivate DataSource dataSource;@Bean(name = "transactionManager")public PlatformTransactionManager transactionManager() {JpaTransactionManager tm = new JpaTransactionManager();tm.setEntityManagerFactory(emf);tm.setDataSource(dataSource);return tm;}}

注釋@EnableTransactionManagement告訴Spring帶有@Transactional注釋的類應(yīng)使用Transactional Aspect包裝。 這樣,@ @Transactional現(xiàn)在可以使用了。

結(jié)論

Spring聲明式事務(wù)管理機(jī)制非常強(qiáng)大,但是很容易被濫用或錯(cuò)誤配置。

在機(jī)制無法正常工作或無法正常工作的情況下進(jìn)行故障排除時(shí),了解其內(nèi)部工作方式將很有幫助。

要牢記的最重要的一點(diǎn)是,實(shí)際上有兩個(gè)概念需要考慮:數(shù)據(jù)庫事務(wù)和持久性上下文,每個(gè)都有其自身不容易顯現(xiàn)的生命周期。

將來的帖子將討論事務(wù)注釋的最常見陷阱以及如何避免它們。

翻譯自: https://www.javacodegeeks.com/2014/06/how-does-spring-transactional-really-work.html

總結(jié)

以上是生活随笔為你收集整理的Spring @Transactional实际如何工作?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。