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?
To perform transaction management within the database using Spring Framework with Hibernate and Annotations, we need an access to the source code to edit it and add @Transactional Annotation to class and methods involved in performing the transaction operations.
Spring supports both programmatic and declarative transaction management. EJBs require an application server, but Spring transaction management can be implemented without the need of an application server.
Remove the following line, it interferes with Spring-managed transactions:
<property name="current_session_context_class">thread</property>
@hephestos: The value for the parameter current_session_context_class
decides the context to which the session (Hibernate session) must be bound with.
By default it is bound with the currently running thread. But when "jta" is used to manage transactions, changing the value of this parameter to "jta" binds the session to the current JTA transaction context.
Basically it defines the context for the sessions. More information: http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/architecture.html#architecture-current-session
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With