How to apply transactions best practice for read operations in Spring MVC using Hibernate?

hibernate, spring, transactions

Solution

I disagree with using SUPPORTS for read operations. Use REQUIRED.

- A transaction is needed anyway to perform every database operation

- Doing several small transactions to read several things at once won't benefit from the first-level cache

- There won't be any isolation between all the subsequent reads, meaning that something not visible to the first read might become visible for the second one

- you'll get lazy loading exceptions when traversing associations

Problem

As it is mentioned in blogs/books (e.g. Java Transactions Design Strategies by Mark Richards), read operations must have the Propagation.SUPPORTS attribute. In a simple Spring 3.1 MVC project with Hibernate 4.1 the scenario is: - Declarative transaction management using @Transactional - sessionFactory of org.springframework.orm.hibernate4.LocalSessionFactoryBean - Transaction manager of org.springframework.orm.hibernate4.HibernateTransactionManager - Service class with @Transactional(propagation=Propagation.REQUIRED) - Function of that Service class that only retrieves a resultset (performs read operation) with @Transactional(propagation=Propagation.SUPPORTS) - Function of read operation retieves the resultset using sessionFactory.getCurrentSession().get() Of course, when a Controller executes the function of read operation, the exception "No Session found for current thread" is raised because a transaction is not started and a session is not obtained. Based on the above configuration (while it is best e.g. non-invasive, less code etc) the Propagation.SUPPORTS attribute cannot be used unless a transaction is started before with Propagation.REQUIRED or Propagation.REQUIRES_NEW. How do we use use Propagation.SUPPORTS for read operations without having to start a transaction e.g. with Propagation.REQUIRED before but still taking advantage the benefits of declarative transaction management? Thank you in advance. Coder, here is the configuration: ``` <tx:annotation-driven transaction-manager="txManager"/> <context:component-scan base-package="com.myapps.service.impl" /> <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${db.driverClassName}" /> <property name="url" value="${db.url}" /> <property name="username" value="${db.username}" /> <property name="password" value="${db.password}" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mappingResources"> <list> <value>.....</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${db.dialect}</prop> <prop key="hibernate.format_sql">true</prop> </props> </property> </bean> ```

Original source