我有一个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之间这种行为差异的清楚解释吗?
它取决于spring的版本,但是通常必须避免在使用Spring时弄乱该属性(除非您将JTA用于事务处理,然后才需要配置它)。
从Hibernate 3.1开始,有一种称为上下文会话的东西,并且该Hibernate提供了CurrentSessionContext接口。有几种实现方式(并且thread是的缩写ThreadLocalSessionContext)。Spring对此类的接口有自己的实现SpringSessionContext。
CurrentSessionContext
thread
ThreadLocalSessionContext
SpringSessionContext
默认情况下,Spring将该属性设置为的Springs实现CurrentSessionContext,当将此属性设置为其他值(JTA除外)时,这将破坏springs管理hibernate会话(从而管理事务)的能力。
现在,在较旧版本的spring(我还假设您还升级了Spring使其可以使用hibernate)与hibernate 3结合使用时,在获取会话方面还涉及到其他技巧(由于与旧版3.x版本的hibernate向下兼容)。这使得Spring较少依赖该属性的值。(Spring为代理创建了一个代理,SessionFactory并从根本上拦截了getSession能够管理会话的方法)。
SessionFactory
getSession