Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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>
like image 592
mike.l Avatar asked May 25 '12 07:05

mike.l


People also ask

How are transactions handled in Hibernate?

In hibernate framework, we have Transaction interface that defines the unit of work. It maintains abstraction from the transaction implementation (JTA,JDBC). A transaction is associated with Session and instantiated by calling session. beginTransaction().

What is the best practice to mark transaction as read-only when code does not write anything to the database?

It's good practice to define the @Transactional(readOnly = true) annotation at the class level and only override it for read-write methods. This way, we can make sure that read-only methods are executed by default on the Replica nodes.

Can we use Hibernate with Spring MVC?

We can simply integrate hibernate application with spring application. In hibernate framework, we provide all the database information hibernate. cfg. xml file.


1 Answers

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
like image 67
JB Nizet Avatar answered Sep 30 '22 22:09

JB Nizet