using current_session_context_class property hibernate 3 hibernate 4
Asked Answered
F

1

11

I have an application with Spring and Hibernate3 running well in production. Following is the config for session factory in Spring's 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>

It is working fine in production.

Now for another project we are migrating to Hibernate4. we copied over the same configuration except using Hibernate 4's SessionFactory,TransacionManager etc. from org.springframework.orm.hibernate4.* package. However it started giving exception saying "Save is not valid without active transaction". After searching a bit many people seemed to have faced the problems and several people suggested not to use

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

property and it worked. It also worked for me. All little information I could gather from the posts that it has something to do with contextual sessions and thread strategy interfering with Spring's session management strategy. But no where I could find any concrete answer.
Also, why did it work with Hibernate3 and not with Hibernate4. What is the difference and what has changed? Every other configuration is same. I am not using @Transactional but the old school XML way.

Can somebody point me to a clear explanation for this behavioral difference between Hibernate3 and Hibernate4?

Fantasm answered 9/11, 2013 at 11:38 Comment(0)
P
10

It depends on the version of spring but in general messing around with that property whilst using Spring must be avoided (unless you use JTA for transactions then you need to configure this).

As of Hibernate 3.1 there is something called contextual sessions and for that hibernate provides the CurrentSessionContext interface. There are several implementations for this (and thread is short for ThreadLocalSessionContext). Spring has its own implementation of this interface the SpringSessionContext class.

Spring by default sets the property to Springs implementation of the CurrentSessionContext, when this is set to something else (other then JTA) this will break springs ability to manage the hibernate session (and thus the transaction).

Now in older versions of spring (and I assume you also upgraded Spring to be able to use hibernate) combined with hibernate 3 there was some other trickery involved regarding getting the session (due to backwards compatibility with older 3.x versions of hibernate). This made Spring less depended on the value of that property. (Spring created a proxy for the SessionFactory and basically intercepted the getSession method to be able to manage the session).

Phenobarbitone answered 10/11, 2013 at 20:9 Comment(4)
Yes I upgraded the Spring from 2.5 to 3.2.4. I guess your answer sufficinelty explains behavioural difference in handling sessions by spring. And its more related to Spring than Hibernate right?(Or both?)Fantasm
However Can you please in detail explain the contextual session and why they were introduced. If you have some useful links other than hibernate docs which explains the whole session handling by hibernate and where and how Spring does the trick of handling these things I would be greatly obliged. Ofcourse I can debug the code, however Right now I need to be more clearer on theory first before digging into codeFantasm
@ShaileshVaishampayan The difference between Spring 2.5 and 3.2 can be explained by the minimal hibernate version (3.2 requires hibernate 3.2 which allowed for a cleaner integration). #7871886 has some more information regarding contextual sessions. But in short before contextual sessions one needed to keep track of the current session themselves (store the session in an instance variable). Now that is delegated to hibernate, and makes it easier for frameworks like hibernate.Phenobarbitone
Thank you. Will look at the linkFantasm

© 2022 - 2024 — McMap. All rights reserved.