Spring – How to integrate spring with hibernate session and transaction management

hibernatespringtransactions

I am a beginner in both hibernate and spring. I have understood about the hibernate transaction demarcation (at least I think so). But after coding a few method like this:

sessionFactory.getCurrentSession().beginTransaction();
//do something here
sessionFactory.getCurrentSession().endTransaction();

I started to want to avoid it and want to have it automatically done outside my method such that I only write the "//do something here" part. I have read about the TransactionProxyFactoryBean and think that the xml configuration is very long and have to be repeated for EVERY classes I want to make transactional so if possible I want to avoid using it.

I tried to use the @Transactional but it doesn't work at all. I have these lines in my applicationContext.xml

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>

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

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

and I have already marked my service classes with @Transactional but I always get the "xxx is not valid without active transaction".
Here is an example code that give me an error (run in unit test btw):

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations =
{
    "classpath:applicationContext.xml"
})
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class UserServiceTest
{
    @Resource
    private UserService userService;

    @Test
    public void testAddUser()
    {
        User us = new User();
        us.setName("any name");
        userService.addUser(us);
    }
}

In this case, the exact error message is: "org.hibernate.HibernateException: save is not valid without active transaction".

UPDATE: I tried calling the userService.addUser() method from outside unit tests (i.e. from actual web application) and I got the same error as well.

This is my hibernate.cfg.xml:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>
        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>
        <!-- Disable the second-level cache -->
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>
        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">update</property>

        <!-- all my mapping resources here -->
    </session-factory>
</hibernate-configuration>

The userService class is marked with @Transactional. I am using hibernate 3.3.2 and spring 2.5.6.

Can I have some advice on how to fix this?

Best Answer

Remove the following line, it interferes with Spring-managed transactions:

<property name="current_session_context_class">thread</property>