11

我有一个 Spring 和 Hibernate3 在生产中运行良好的应用程序。以下是 Spring 的 applicationContext.xml 中会话工厂的配置

       <bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="mappingDirectoryLocations">
        <list>
            <value>classpath:/hibernate</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect
            </prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.use_sql_comments">true</prop>
            <prop key="hibernate.max_fetch_depth">2</prop>
            <prop key="hibernate.autocommit">false</prop>
            <prop key="hibernate.current_session_context_class ">thread</prop>
                            <prop key="hibernate.generate_statistics">true</prop>
            <prop key="hibernate.jdbc.batch_size">20</prop>
        </props>
    </property>
</bean>

<bean id="txManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean 
    below) -->
<tx:advice id="txAdvice" transaction-manager="txManager">
    <!-- the transactional semantics... -->
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED" />
        <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="count*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="validate*" propagation="SUPPORTS"
            read-only="true" />
        <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="login" propagation="SUPPORTS" read-only="true" />
    </tx:attributes>
</tx:advice>

<!-- ensure that the above transactional advice runs for any execution of 
    an operation defined by the service interfaces -->
<aop:config>
    <aop:pointcut id="projectServiceOperation"
        expression="execution(* com.service.project.IProjectService.*(..))" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="projectServiceOperation" />
</aop:config>

它在生产中运行良好。

现在对于另一个项目,我们正在迁移到 Hibernate4。我们复制了相同的配置,除了使用来自 org.springframework.orm.hibernate4.* 包的 Hibernate 4 的 SessionFactory、TransacionManager 等。但是它开始给出异常说“如果没有活动的交易,保存是无效的”。搜索了一下,好像很多人都遇到了问题,有几个人建议不要使用

        <prop key="hibernate.current_session_context_class ">thread</prop>

财产,它的工作。它也对我有用。我可以从帖子中收集到的所有信息都与上下文会话和干扰 Spring 会话管理策略的线程策略有关。但是我找不到任何具体的答案。
另外,为什么它适用于 Hibernate3 而不是 Hibernate4。有什么区别和改变了什么?其他所有配置都相同。我没有使用@Transactional,而是使用老式的 XML 方式。

有人可以指出我对 Hibernate3 和 Hibernate4 之间的这种行为差异的明确解释吗?

4

1 回答 1

10

这取决于 spring 的版本,但通常必须避免在使用 Spring 时弄乱该属性(除非您使用 JTA 进行事务,否则您需要配置它)。

从 Hibernate 3.1 开始,有一种称为上下文会话的东西,为此 hibernate 提供了CurrentSessionContext接口。有几种实现方式(并且thread是 的缩写ThreadLocalSessionContext)。Spring有自己实现这个接口的SpringSessionContext类。

默认情况下,Spring 将属性设置为 Springs 的实现CurrentSessionContext,当它设置为其他东西(除 JTA 之外)时,这将破坏 springs 管理休眠会话(以及事务)的能力。

现在在旧版本的 spring 中(我假设你还升级了 Spring 以便能够使用 hibernate)与 hibernate 3 相结合,在获取会话方面涉及一些其他技巧(由于与旧 3.x 版本的 hibernate 向后兼容)。这使得 Spring 不再依赖该属性的值。(Spring创建了一个代理SessionFactory并且基本上拦截了getSession能够管理会话的方法)。

于 2013-11-10T20:09:08.770 回答