2010-09-22 116 views
2

我試圖縮短這個與我認爲相關的東西,我希望這是足夠的,而不是壓倒性的。請幫忙!爲什麼我的(spring)HibernateTransactionManager不能在wicket中工作?

我將一個小檢票+的DataBinder + hibernate的 Web應用程序使用檢票+ Spring + Hibernate的。我有一個DAO服務類,由Spring注入一個hibernate SessionFactory。我能夠使用會話工廠執行只讀操作(默認情況下,自動提交功能處於打開狀態)。我想要做的是使用HibernateTransactionManager和@Transactional註釋來執行事務操作。

我定義了一個DAO服務實現,它使用一個注入的SessionFactory的方法標記@Transactional:

public class DAO implements IDAO { 
@SpringBean 
private SessionFactory sessionFactory; 

public DAO() { 
    super(); 
} 

@Transactional 
public Object execute(SessionUnit sessionUnit) { 
    Session sess = sessionFactory.getCurrentSession(); 
    Object result; 
    result = sessionUnit.run(sess); 
    sess.flush(); 
    return result; 
} 

public void setSessionFactory(SessionFactory sessionFactory) { 
    this.sessionFactory = sessionFactory; 
} 

@Transactional 
public boolean isObjectPersistent(Object object) { 
    return sessionFactory.getCurrentSession().contains(object); 
} 
} 

當我嘗試調用isObjectPersistent(),我得到一個休眠例外,因爲沒有人叫session.beginTransaction ():

Caused by: org.hibernate.HibernateException: contains is not valid without active transaction 
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:338) 
at $Proxy38.contains(Unknown Source) 
at com.gorkwobbler.shadowrun.karma.db.hibernate.DAO.isObjectPersistent(DAO.java:35) 
(reflection stuff omitted...) 
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149) 
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) 
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106) 
(reflection stuff omitted...) 
at org.apache.wicket.proxy.LazyInitProxyFactory$JdkHandler.invoke(LazyInitProxyFactory.java:416) 
at org.apache.wicket.proxy.$Proxy36.isObjectPersistent(Unknown Source) 

我也是從完整的堆棧跟蹤時會被調用的OpenSessionInViewFilter注意到,我不知道這是相關的。讓我知道你是否需要堆棧跟蹤的其餘部分。

如果我創建一個自定義WebRequestCycle子類,它開始一個事務,我可以通過這個。這在我看來破壞了@Transactional的目的,而且我的實現也變成了問題。

這裏是我的applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<!-- Reference: http://wicketinaction.com/2009/06/wicketspringhibernate-configuration/ --> 
<beans default-autowire="autodetect" 
    xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd 
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd 
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> 

    <!-- bean definitions --> 
    <bean id="wicketApplication" class="com.gorkwobbler.shadowrun.karma.view.wicket.core.WicketApplication" /> 

    <bean id="placeholderConfigurer" 
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
     <property name="ignoreUnresolvablePlaceholders" value="false" /> 
     <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /> 
     <property name="ignoreResourceNotFound" value="false" /> 
     <property name="locations"> 
      <list> 
       <value>classpath*:/application.properties</value> 
      </list> 
     </property> 
    </bean> 

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> 
     <property name="driverClassName"> 
      <value>${jdbc.driver}</value> 
     </property> 
     <property name="url"> 
      <value>${jdbc.url}</value> 
     </property> 
     <property name="username"> 
      <value>${jdbc.username}</value> 
     </property> 
     <property name="password"> 
      <value>${jdbc.password}</value> 
     </property> 
    </bean> 

    <tx:annotation-driven transaction-manager="txManager" /> 

    <!-- setup transaction manager --> 
    <bean id="txManager" 
     class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory"> 
      <ref bean="sessionFactory" /> 
     </property> 
    </bean> 

    <!-- hibernate session factory --> 
    <bean id="sessionFactory" 
     class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
     <property name="configLocation"> 
      <value>classpath:/hibernate.cfg.xml</value> 
     </property> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="hibernateProperties"> 
      <props> 
      </props> 
     </property> 
     <property name="packagesToScan"> 
      <list> 
       <value>com.gorkwobbler.shadowrun.karma.domain</value> 
       <value>com.gorkwobbler.shadowrun.karma.domain.*</value> 
      </list> 
     </property> 
    </bean> 

    <bean id="dao" 
     class="com.gorkwobbler.shadowrun.karma.db.hibernate.DAO"> 
     <property name="sessionFactory"> 
      <ref bean="sessionFactory" /> 
     </property> 
    </bean> 

    <!-- Don't know what this is for, but it was in the sample config I started from --> 
    <!-- <context:component-scan base-package="com.gorkwobbler.shadowrun.karma" /> --> 
</beans> 

我怎樣才能讓我的DAO開始交易,在該方法中,或者在錯誤回滾月底提交?我想使用可能的最小/標準配置;如果給出選擇,我更喜歡對XML的註釋。

編輯:

我修改上面的ApplicationContext來刪除AOP配置的東西,這是不工作的,反正。

使用調試器時,我確定存儲在TransactionInterceptor的會話持有者映射中的SessionImpl與SessionOmp方法中檢索到的SessionImpl不同,當我調用sessionFactory.getCurrentSession()時。任何人都可以解釋爲什麼這是?我究竟做錯了什麼?魔法不起作用。 =(

編輯

我也注意到在我的控制檯以下消息啓動時:

WARN - stractEhcacheRegionFactory - No TransactionManagerLookup found in Hibernate config, XA Caches will be participating in the two-phase commit! 

回答

2

事實證明,問題實際上並不在我發佈的配置信息中。抱歉!

我上面的配置鏈接外化的hibernate.cfg.xml,宣佈以下屬性:

<!-- Enable Hibernate's automatic session context management --> 
    <property name="current_session_context_class">thread</property> 

我一定是從一些樣本休眠配置文件複製某處此。此屬性導致我的SessionFactory忽略Spring提供的會話上下文,並在其位置使用線程本地上下文。刪除這個屬性解決了這個問題(如果沒有指定,hibernate默認使用JTA上下文)。

+0

我有同樣的問題,但我當前的會話上下文類設置爲: org.hibernate.context.ThreadLocalSessionContext 刪除它會引發異常 – Eildosa 2012-06-15 09:13:56

2

這可以做得更簡單閱讀本節13.3.3 (Hibernate) Declarative transaction demarcation,尤其是最後一部分。這通常是足夠的配置,如果你使用@Transactional

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:aop="http://www.springframework.org/schema/aop" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xsi:schemaLocation=" 
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
     http://www.springframework.org/schema/tx 
     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
     http://www.springframework.org/schema/aop 
     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> 

    <!-- SessionFactory, DataSource, etc. omitted --> 

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

    <tx:annotation-driven/> 

    <bean id="myProductService" class="product.SimpleProductService"> 
    <property name="productDao" ref="myProductDao"/> 
    </bean> 

</beans> 

爲了回答您的評論:

沒有,如果你通過Spring注入部件,春天確實佈線,Hibernate並不需要知道關於春天的任何事情,那就是使用彈簧的全部要點(去耦各個層)。服務和道是不是每個人都使用的分離。重要的部分是由接口支持的公共方法被標記爲事務性的,因爲標記爲事務性的所有方法將被執行事務處理的代理攔截,而其他方法則不會。

您可能想了解有關Declarative Transaction Managmenet in Spring的常規部分以瞭解過程(這適用於所有事務性技術,而不僅僅是休眠)。

+0

我刪除了AOP配置的東西(它什麼都沒做,它沒有工作);否則,你發佈的內容與我已有的相同(據我所知)。我仍然有同樣的問題。我沒有單獨的服務和DAO類。這對這個問題有重要意義嗎? – RMorrisey 2010-09-22 08:35:33

+0

我正在使用wicket,它不是一個EJB容器,所以我想我可能需要使用AOP的東西來做一些額外的工作才能讓@Transactional正常工作?休眠本身是否需要以某種方式瞭解事務管理器? – RMorrisey 2010-09-22 08:41:25

+0

我也使用spring和wicket,在tomcat中沒有ejb容器。對於大多數目的,Spring提供了EJB容器所需的一切。另外,請參閱我的更新回答 – 2010-09-22 08:58:54

相關問題