Spring和Hibernate 4:如果没有活动事务,get就无效

msk*_*app 0 spring hibernate spring-annotations spring-transactions

我正在使用Spring注释和hibernate来创建DAO.我使用的是Spring 3.2.5和hibernate 4.3.3.出于某种原因,我一直得到这个例外:

org.hibernate.HibernateException:如果没有活动事务,则get无效

这是我的春季应用程序上下文的相关部分:

<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>
Run Code Online (Sandbox Code Playgroud)

这是我的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));
    }
Run Code Online (Sandbox Code Playgroud)

顺便说一下@Transactional是春天的,而不是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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的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';
Run Code Online (Sandbox Code Playgroud)

此外,我的所有代码都在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>
Run Code Online (Sandbox Code Playgroud)

这是例外:

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
Run Code Online (Sandbox Code Playgroud)

基于此,也许我错过了我的pom中的依赖,或者有一个坏的依赖.我会试着找出......

我使用的是mysql-connector-java版本5.1.29,也许这是不兼容的?

JB *_*zet 7

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