2010-01-18 53 views
6

我有一個與Spring設置的Web應用程序來創建我的休眠會話工廠(單身人士)和會議和事務(都是請求作用域),但它正在銷燬會話並以錯誤的順序進行交易。我如何配置它,以便在會話之前銷燬事務?這是我的春天applicationContext.xml文件:試圖以正確的順序銷燬豆與春

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" 
     "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> 
<beans> 
    <bean id="hibernateSessionFactory" scope="singleton" 
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
    <property name="configLocation" value="classpath:hibernate.cfg.xml" /> 
    </bean> 

    <!-- The per-http request hibernate session --> 
    <bean id="hibernateSession" factory-bean="hibernateSessionFactory" 
    factory-method="openSession" destroy-method="close" scope="request" /> 

    <!-- The per-http request transaction (i need this to be destroyed BEFORE the session) --> 
    <bean id="hibernateTransaction" factory-bean="hibernateSession" 
    factory-method="beginTransaction" destroy-method="commit" scope="request" /> 
</beans> 

而這裏的,顯示它在會議閉幕它關閉前交易日誌:

16111 [http-8080-3] DEBUG org.springframework.beans.factory.support.DisposableBeanAdapter - Invoking destroy method 'close' on bean with name 'hibernateSession' 
16111 [http-8080-3] DEBUG org.hibernate.jdbc.ConnectionManager - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)] 
16111 [http-8080-3] DEBUG com.mchange.v2.resourcepool.BasicResourcePool - trace [email protected] [managed: 4, unused: 3, excluded: 0] (e.g. [email protected]) 
16111 [http-8080-3] DEBUG org.springframework.beans.factory.support.DisposableBeanAdapter - Invoking destroy method 'commit' on bean with name 'hibernateTransaction' 
16111 [http-8080-3] DEBUG org.hibernate.transaction.JDBCTransaction - commit 
16111 [http-8080-3] WARN org.springframework.beans.factory.support.DisposableBeanAdapter - Invocation of destroy method 'commit' failed on bean with name 'hibernateTransaction' 
org.hibernate.SessionException: Session is closed 

回答

4

似乎是destory方法調用非單獨作用域bean的順序完全失去控制。從文檔(3.4.3 Using depends-on):

的依賴,在bean定義屬性可以在單豆的情況下,只有,同時指定了初始化時間 的依賴,並一個相應的破壞時間 依賴

您可以創建一個輔助對象和委託創建和bean的破壞它:

public class HelperObject 
{ 
    private SessionFactory factory; 
    private Session session; 
    private Transaction tx; 

    public void init() 
    { 
     session = factory.createSession(); 
     tx = session.beginTransaction(); 
    } 

    public void destroy() 
    { 
     tx.commit(); 
     session.close(); 
    } 

    ... 
} 

-

<bean id = "helperObject" class = "HelperObject" scope = "request" init-method = "init" destroy-method = "destroy"> 
    <property name = "factory" ref = "hibernateSessionFactory" /> 
</bean> 

<bean id="hibernateSession" factory-bean="helperObject" 
    factory-method="getSession" scope="request" /> 

<bean id="hibernateTransaction" factory-bean="helperObject" 
    factory-method="getTransaction" scope="request" /> 

而且,畢竟,它可能不是在Spring中管理Hibernate會話和事務的最佳方式。考慮使用Spring的內置Hibernatetransactions支持。

編輯: 好,管理事務的正確方法是

  • 你不需要請求範圍sessiontransaction
  • 你不應該呼籲createSession會話工廠由org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean返回。您可以將此會話工廠注入到您的bean中,並在需要會話時致電getCurrentSession,它會正常工作。
  • 您可以使用聲明式事務管理(@Transactional註釋事務方法)。要使其工作,您應該添加到您的配置:

<bean id="transactionManager" 
    class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="hibernateSessionFactory"/> 
</bean> 

<tx:annotation-driven/> 
  • 欲瞭解更多信息,請參見上述
+0

嗨, 我有一個懷疑,春天有內置的選項管理會議/ txn,但是在閱讀這兩個鏈接後,我仍然沒有接近理解他們的工作方式。我想我會選擇你的'助手班'選項,這是一個好主意。我覺得春天無法控制摧毀秩序是一件可惜的事情,但對我來說這並不是那麼重要。 – Chris 2010-01-18 02:02:10

+0

我看了看那兩個鏈接,我看不到我怎麼可以使用spring事務管理器(或其他任何東西)給我一個會話和事務,我可以注入到我的動作中,它似乎只給我一個會話工廠,然後我可以調用'getCurrentSession()',這對我來說看起來不太好。 – Chris 2010-01-18 02:03:57

+0

我猜我在問什麼,如果這不是最好的方式,那麼*是用spring來管理session/txns的最好方法? – Chris 2010-01-18 02:10:00

1

你可以聲明hibernateTransactiondepends-onhibernateSession。由於容器將以依賴順序實例化bean(禁止循環依賴),並以反向依賴順序將它們拆除,所以這應該能夠實現。

+1

它不適用於請求範圍的bean。根據文檔,depends-on僅爲單一作用域bean指定銷燬順序。 – axtavt 2010-01-18 01:26:09

+0

是的,我已經試過依賴,它沒有幫助。不過,謝謝你的回答! – Chris 2010-01-18 01:50:16

1

交易應的服務,如果你遵循了Spring成語相關的鏈接。會話是Web層對象,與服務層完全分離。這對我來說聽起來像是你犯了糾纏你的Web層與服務層的錯誤。最好把它們分開;你不可能在這個安排上遇到這個問題。

+0

給我打了半打,以瞭解你的意思!我現在假設當你說'服務'時,你的意思是'商業'層類(例如類似'FindEventById()'的類)。所以服務是關心交易的服務。我想這是有道理的。 – Chris 2010-01-18 03:59:22

+0

好吧,我已經嘗試了你的建議,但現在我遇到了問題,即我的服務層加載了我的事件對象,但是當我嘗試訪問返回對象中的字段時,它有一個「LazyInitializationException - 無法初始化代理 - 沒有會話「的錯誤,大概是因爲會議已經關閉,因爲我已經完成了對服務層的訪問。所以我認爲會議仍然需要以某種方式與網絡請求綁定,任何建議你如何克服這一點? – Chris 2010-01-18 05:04:20

+0

啊哈!得到它的工作:需要在web.xml中設置OpenSessionInViewFilter。唷! – Chris 2010-01-18 05:20:06