mike.l
mike.l

Reputation: 219

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:

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>

Upvotes: 5

Views: 2322

Answers (2)

coder
coder

Reputation: 4466

Transaction is not always required for Propagation.SUPPORTS. Propagation.SUPPORTS: Support a current transaction, execute non-transactionally if none exists.

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 692063

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

Upvotes: 6

Related Questions