gpt4 book ai didi

java - 为什么我的 (spring)HibernateTransactionManager 不能在 wicket 中工作?

转载 作者:塔克拉玛干 更新时间:2023-11-02 07:57:54 26 4
gpt4 key购买 nike

我试图将其缩短为我认为相关的内容,我希望它足够而不是压倒性的。请帮忙!

我正在将一个小型 wicket+databinder+hibernate 网络应用程序转换为使用 wicket+spring+hibernate。我有一个 DAO 服务类,带有一个由 Spring 注入(inject)的 hibernate SessionFactory。我可以使用 session 工厂执行只读操作(默认情况下自动提交处于启用状态)。我想做的是使用 HibernateTransactionManager 和 @Transactional 注释来执行事务操作。

我定义了一个 DAO 服务实现,它在标记为@Transactional 的方法中使用注入(inject)的 SessionFactory:

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() 时,我得到一个 hibernate 异常,因为没有人调用过 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 的 session 持有者映射中的 SessionImpl 与调用 sessionFactory.getCurrentSession() 时在 DAO 方法中检索到的 SessionImpl 不是同一个 session 。谁能解释这是为什么?我究竟做错了什么?魔术不起作用。 =(

编辑

我还注意到在启动期间我的控制台中出现以下消息:

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

最佳答案

原来问题其实不在我发布的配置信息中。对不起!

我上面的配置链接到一个外部化的 hibernate.cfg.xml,它声明了以下属性:

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

我一定是从某处的一些示例 hibernate 配置文件中复制了它。此属性导致我的 SessionFactory 忽略 spring 提供的 session 上下文,并在其位置使用线程本地上下文。删除此属性可解决问题(如果未指定,hibernate 默认使用 JTA 上下文)。

关于java - 为什么我的 (spring)HibernateTransactionManager 不能在 wicket 中工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3767065/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com