【问题标题】:Spring and Hibernate 4: get is not valid without active transactionSpring和Hibernate 4:没有活动事务,get无效
【发布时间】:2014-04-02 16:03:05
【问题描述】:

我正在使用 Spring 注释和休眠来创建 DAO。我正在使用 Spring 3.2.5 和休眠 4.3.3。出于某种原因,我不断收到此异常:

org.hibernate.HibernateException: get is not valid without active transaction

这是我的 spring 应用上下文的相关部分:

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

        <!-- Pick up the HibernateHouseDAO spring bean -->
        <context:component-scan base-package="jinvestor.jhouse.download" />

        <bean id="sessionFactory"
            class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="annotatedClasses">
                <list>
                    <value>jinvestor.jhouse.core.HouseEntity</value>
                </list>
            </property>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                    <prop key="hibernate.current_session_context_class">thread</prop>
<!--                    <prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</prop> -->
                </props>
            </property>
        </bean>

        <bean id="dataSource"
            class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="${dataSource.driver}" />
            <property name="url" value="${dataSource.url}" />
            <property name="username" value="${dataSource.username}" />
            <property name="password" value="${dataSource.password}" />
        </bean>

        <bean id="transactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>

这是我的 DAO:

@Repository("dao")
@Profile("mysql")
@Transactional
public class HibernateHouseDAO implements HouseDAO {

    private final SessionFactory sessionFactory;

    @Autowired
    public HibernateHouseDAO(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    public House load(long id) {

        // this throws a nosuch method error for openSession.
//      Session session = SessionFactoryUtils.getSession(sessionFactory, false);

        // this throws an error on the lack of a transaction.
        Session session = sessionFactory.getCurrentSession();
        HouseEntity entity = (HouseEntity) session.get(HouseEntity.class, id);
        return House.fromEntity(entity);
    }

    @Override
    public void save(House house) {
        sessionFactory.getCurrentSession().save(new HouseEntity(house));
    }

顺便说一句,@Transactional 是 spring 的,而不是 javax.transaction。这是我的单元测试:

// MT stands for manual test
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/applicationContext.xml"})
@ActiveProfiles(profiles={"test","mysql"})
public class HibernateHouseDAOMT extends HouseDAOTest {

    @Autowired
    private HouseDAO dao;

    @Override
    public HouseDAO getDao() {
        return dao;
    }
}

这是我的 SQL 架构,以防您需要了解它:

create table homes (zpid BIGINT PRIMARY KEY NOT NULL, address VARCHAR(200) NOT NULL,squareFeet INT UNSIGNED,soldPrice INT UNSIGNED, latitude INT,longitude INT,lastSoldDate DATE, yearBuilt YEAR,acres FLOAT UNSIGNED,beds TINYINT UNSIGNED,baths TINYINT UNSIGNED, INDEX (address)) ENGINE = 'INNODB';

另外,我所有的代码都在 github 上,以防你想看到我没有在这里复制的东西。这是github上的项目根:

https://github.com/msknapp/JInvestor/tree/master/JHouse/jhouse.download

请帮我解决这个问题。

==================== 更新:

切换到 Hibernate 事务管理器:

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

这里是个例外:

java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:122)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:312)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: org.hibernate.engine.spi.SessionFactoryImplementor.getConnectionProvider()Lorg/hibernate/service/jdbc/connections/spi/ConnectionProvider;
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1512)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:296)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:628)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:120)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:248)
    at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContextInternal(CacheAwareContextLoaderDelegate.java:64)
    at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:91)
    ... 25 more
Caused by: java.lang.NoSuchMethodError: org.hibernate.engine.spi.SessionFactoryImplementor.getConnectionProvider()Lorg/hibernate/service/jdbc/connections/spi/ConnectionProvider;
    at org.springframework.orm.hibernate4.SessionFactoryUtils.getDataSource(SessionFactoryUtils.java:90)
    at org.springframework.orm.hibernate4.HibernateTransactionManager.afterPropertiesSet(HibernateTransactionManager.java:335)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1571)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1509)
    ... 40 more

基于此,我的 pom 中可能缺少依赖项,或者依赖项不好。我会试着找出答案...

我使用的是 mysql-connector-java 5.1.29 版本,可能不兼容?

【问题讨论】:

  • 你应该使用 HibernateTransactionManager 而不是 DataSourceTransactionManager。
  • 我之前试过,应用上下文加载失败。它甚至没有告诉我为什么。
  • 如果加载失败,那么你应该在日志中有一个堆栈跟踪。使用 HibernateTransactionManager,编辑您的问题以显示您更新的代码,并发布您获得的异常的堆栈跟踪。
  • @msknapp 在 HibernateTransactionManager 中,您注入的是数据源还是会话工厂。你需要会话工厂。
  • 好的,我发布了更新,我认为这将归结为 maven 依赖问题。

标签: spring hibernate spring-transactions spring-annotations


【解决方案1】:

您使用的是 Spring 3.2.5,它与您使用的最新 Hibernate 4.3.3 版本不兼容。 Hibernate 4.3 确实决定更改SessionFactoryImplementor.getConnectionProvider() 返回的ConnectionProvider 的包。使用最新的 Spring 版本,或者使用 Hibernate 4.2,应该会运行得更好。

【讨论】:

  • 我将 spring 版本切换到 4.0.2.RELEASE 和 hibernate-core 到 4.2.0.Final,我的应用程序上下文现在加载,但我回到了原始异常消息。
  • 尝试删除属性 hibernate.current_session_context_class。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-16
  • 1970-01-01
  • 2014-10-29
  • 2015-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多