javascript
通过Spring集成从Hibernate 3迁移到4
本周是時(shí)候?qū)⑽覀兊拇a庫(kù)升級(jí)到最新的Hibernate 4.x了。 我們推遲了遷移(仍在Hibernate 3.3上),因?yàn)?.x分支的較新維護(hù)版本需要對(duì)API進(jìn)行一些更改,這些更改顯然仍在不斷變化中。 一個(gè)示例是UserType API,該API仍然存在缺陷,將在Hibernate 4中完成。遷移非常順利。 使UserType適應(yīng)新界面非常簡(jiǎn)單。 到處都有一些刺激,但沒(méi)有痛苦。
需要注意的是Spring集成。 如果您以前將Spring與Hibernate結(jié)合使用,則將使用LocalSessionFactoryBean (或AnnotationSessionFactoryBean )創(chuàng)建SessionFactory 。 對(duì)于休眠4
在自己的程序包中有一個(gè)單獨(dú)的程序:org.springframework.orm。 hibernate4而不是org.springframework.orm。 休眠3 。 hibernate 4包中的LocalSessionFactoryBean將同時(shí)用于映射文件和帶注釋的實(shí)體,因此兩種樣式都只需要一個(gè)。
升級(jí)完成后,我們的所有測(cè)試都在運(yùn)行,并且使用本地Hibernate事務(wù)管理器在Tomcat上的應(yīng)用程序也運(yùn)行良好。 但是,當(dāng)使用JTA事務(wù)(和Spring的JtaTransactionManager )在Glassfish上運(yùn)行時(shí),在調(diào)用sessionFactory.getCurrentSession()時(shí),我們得到了“未找到當(dāng)前線程的會(huì)話” 。
因此,似乎我錯(cuò)過(guò)了與JTA配置有關(guān)的內(nèi)容。 像通常使用Spring-Hibernate集成一樣,讓Spring驅(qū)動(dòng)事務(wù)。 您指定一個(gè)事務(wù)管理器,Spring確保所有資源都已在事務(wù)管理器中注冊(cè),并最終調(diào)用提交或回滾。 Spring將與Hibernate集成,因此可確保在事務(wù)提交之前刷新會(huì)話。
使用hibernate 3和hibernate 3 Spring集成時(shí),會(huì)話綁定到本地線程。 此技術(shù)使您可以使用sessionFactory.getCurrentSession()獲取活動(dòng)事務(wù)中任何位置的打開(kāi)會(huì)話。 本地HibernateTransactionManager和JtaTransactionManager都是這種情況。 但是,從hibernate 4集成開(kāi)始,hibernate會(huì)話將綁定到當(dāng)前正在運(yùn)行的JTA事務(wù)。
從用戶的角度來(lái)看,什么都沒(méi)有改變,因?yàn)閟essionFactory.getCurrentSession()仍會(huì)完成其工作。 但是,當(dāng)運(yùn)行JTA時(shí),這意味著Hibernate必須能夠查找事務(wù)管理器以能夠向當(dāng)前正在運(yùn)行的事務(wù)中注冊(cè)會(huì)話。 如果您來(lái)自帶有Spring的Hibernate 3,這是新的,實(shí)際上,您不必在Hibernate SessionFactory (或LocalSessionFactoryBean )配置中配置任何與事務(wù)有關(guān)的內(nèi)容。 事實(shí)證明,通過(guò)Hibernate 4 Spring集成,事務(wù)管理器查找配置實(shí)際上是由hibernate完成的,而不是由Spring的LocalSessionFactoryBean完成的 。 解決方案非常簡(jiǎn)單。 將其添加到Hibernate( LocalSessionFactoryBean )配置中解決了我們的問(wèn)題:
<prop key="hibernate.transaction.jta.platform"> org.hibernate.service.jta.platform.internal.SunOneJtaPlatform </prop>然后,應(yīng)將“ SunOneJtaPlatform”替換為反映您的容器的子類。
有關(guān)可用的子類,請(qǐng)參閱API文檔 。 此類實(shí)際上是在告訴Hibernate如何為您的環(huán)境查找事務(wù)管理器。 如果您不進(jìn)行配置,則Hibernate不會(huì)將會(huì)話綁定到任何東西,因此不會(huì)引發(fā)異常。 還有一個(gè)屬性:
hibernate.current_session_context_class它應(yīng)該指向org.springframework.orm.hibernate4.SpringSessionContext ,但這是由LocalSessionFactoryBean自動(dòng)完成的,因此無(wú)需在配置中指定它。
解決了我的“當(dāng)前會(huì)話未找到會(huì)話”問(wèn)題后,還有另一個(gè)問(wèn)題。 成功提交事務(wù)后,將看不到對(duì)事務(wù)內(nèi)部的數(shù)據(jù)庫(kù)所做的更改。 經(jīng)過(guò)一番研究,我發(fā)現(xiàn)沒(méi)有人在調(diào)用session.flush() 。 在進(jìn)行hibernate 3集成時(shí),注冊(cè)了SpringSessionSynchronization ,它將在事務(wù)提交之前(在beforeCommmit方法中)調(diào)用session.flush( )。
在hibernate 4集成中,注冊(cè)了SpringFlushSynchronization , 顧名思義 ,它還將執(zhí)行刷新。 但是,這僅在TransactionSynchronization的實(shí)際“刷新”方法中實(shí)現(xiàn),并且永遠(yuǎn)不會(huì)調(diào)用此方法。
我在Spring Bugtracker上對(duì)此提出了一個(gè)問(wèn)題 ,其中包括兩個(gè)示例應(yīng)用程序,它們清楚地說(shuō)明了該問(wèn)題。 第一個(gè)使用的是Hibernate 3,另一個(gè)使用的是完全相同的應(yīng)用程序,但是這次使用的是hibernte4。第二個(gè)將顯示實(shí)際上沒(méi)有任何信息持久化到數(shù)據(jù)庫(kù)中(兩個(gè)應(yīng)用程序都在最新的Glassfish 3.1.2下進(jìn)行了測(cè)試)。似乎正在創(chuàng)建一個(gè)環(huán)繞@Transactional注釋的沖洗Aspect。 使用order屬性,可以命令在刷新Aspect之前應(yīng)用事務(wù)注釋。 這樣,您的Aspect仍在事務(wù)內(nèi)部運(yùn)行,并且能夠刷新會(huì)話。 它可以通過(guò)注入SessionFactory (一種方式或另一種方式)然后調(diào)用sessionFactory.getCurrentSession()。flush()來(lái)以正常方式獲取會(huì)話。
<tx:annotation-driven order="1"><bean id="flushinAspect" clas="..."><property name="order" value="2"> </property></bean> </tx:annotation-driven>或者,如果使用注釋配置:
@EnableTransactionManagement(order=1)更新:
關(guān)于此問(wèn)題有一些反饋。 事實(shí)證明,這似乎不是Spring Hibernate集成中的錯(cuò)誤,而是缺少的Hibernate配置元素。 顯然,“ hibernate.transaction.factory_class”需要設(shè)置為JTA,默認(rèn)值為JDBC,它依賴于Hibernate Transaction API進(jìn)行顯式事務(wù)管理。 通過(guò)將此設(shè)置為JTA,休眠將注冊(cè)必要的同步,該同步將執(zhí)行刷新。 見(jiàn)春
https://jira.springsource.org/browse/SPR-9404
更新2:
事實(shí)證明,在按照上一個(gè)問(wèn)題建議的配置進(jìn)行糾正后,仍然存在問(wèn)題。 我將不重復(fù)任何事情,您可以在我在此處提交的第二個(gè)錯(cuò)誤條目中找到詳細(xì)信息: https : //jira.springsource.org/browse/SPR-9480它基本上可以歸結(jié)為在JTA場(chǎng)景中在配置了JtaTransactionFactory的情況下,hibernate不會(huì)檢測(cè)到它在事務(wù)中,因此將不執(zhí)行中間刷新。 配置了JtaTransactionFactory之后,您應(yīng)該通過(guò)Hibernate API而不是外部(在我們的例子中為Spring)機(jī)制來(lái)控制事務(wù)。 副作用之一是在某些情況下您可能正在讀取陳舊的數(shù)據(jù)。
例:
//[START TX1] Query query = session.createQuery('from Person p where p.firstName = :firstName and p.lastName = :lastName'); Person johnDoe = (Person)query.setString('firstName','john').setString('lastName','doe').uniqueResult(); johnDoe.setFirstName('Jim'); Person jimDoe = (Person)query.setString('firstName','jim').setString('lastName','doe').uniqueResult(); //[END TX1]發(fā)生的情況是,在第5行執(zhí)行第二個(gè)查詢時(shí),hibernate應(yīng)該檢測(cè)到它應(yīng)該刷新對(duì)第4行的附加實(shí)體所做的先前更新(將名稱從“ john”更新為“ jim”)。 但是,由于休眠不知道它在一個(gè)活動(dòng)事務(wù)中運(yùn)行,因此中間刷新不起作用。 在事務(wù)提交之前,它將僅刷新一次。 這會(huì)導(dǎo)致數(shù)據(jù)過(guò)時(shí),因?yàn)榈诙€(gè)查詢將找不到“ jim”,而是返回null。 解決方案(請(qǐng)參閱問(wèn)題中Juergen Hoeller的答復(fù))是將hibernate.transaction.factory_class配置為org.hibernate.transaction.CMTTransactionFactory 。 剛開(kāi)始我有點(diǎn)懷疑,因?yàn)镃MT使EJB容器成為現(xiàn)實(shí)。 但是,如果您閱讀有關(guān)CMTTransaction的Java文檔,則確實(shí)有道理:
/*** Implements a transaction strategy for Container Managed Transaction (CMT) scenarios. All work is done in* the context of the container managed transaction.** The term 'CMT' is potentially misleading; the pertinent point simply being that the transactions are being* managed by something other than the Hibernate transaction mechanism.** Additionally, this strategy does *not* attempt to access or use the {@link javax.transaction.UserTransaction} since* in the actual case CMT access to the {@link javax.transaction.UserTransaction} is explicitly disallowed. Instead* we use the JTA {@link javax.transaction.Transaction} object obtained from the {@link TransactionManager} 之后,一切似乎都正常。 綜上所述,如果您希望休眠狀態(tài)通過(guò)UserTransaction管理JTA事務(wù),則應(yīng)使用JtaTransactionFactory。 在這種情況下,您必須使用Hibernate API來(lái)控制事務(wù)。 如果還有其他人管理事務(wù)(Spring,EJB容器……),則應(yīng)改用CMTTransactionFactory。 然后,通過(guò)使用javax.transaction.TransactionManager檢查活動(dòng)的javax.transaction.Transaction,Hibernate將恢復(fù)為注冊(cè)同步。 如果彈出任何其他問(wèn)題,我將相應(yīng)地更新此條目。
參考:在Koen Serneels –技術(shù)博客博客上,我們的JCG合作伙伴 Koen Serneels 通過(guò)Spring集成從Hibernate 3遷移到4 。
翻譯自: https://www.javacodegeeks.com/2013/03/migrating-from-hibernate-3-to-4-with-spring-integration.html
總結(jié)
以上是生活随笔為你收集整理的通过Spring集成从Hibernate 3迁移到4的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 成都民俗 成都的风俗介绍
- 下一篇: 三分钟瘦成筷子腿 瘦成筷子腿的小妙招