2010-09-22 109 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

相关问题