title: Spring JPA transaction over multiple methods
body: <p>I'm using Spring 3.2 with JPA and Hibernate 4 in a web application running in Tomcat 7. The application is divided into controller, service an DAO classes. The service classes have an annotated transaction configuration at class and method level. The DAOs are plain JPA with entity manager injected by @PersistenceContext annotation.</p>
  
  <pre><code>@Service("galleryService")
  @Transactional(propagation=Propagation.SUPPORTS, readOnly=true)
  public class GalleryServiceImpl implements GalleryService {
  
    @Override
    public Picture getPicture(Long pictureId) {
      return pictureDao.find(pictureId);
    }
  
    @Override
    public List&lt;PictureComment&gt; getComments(Picture picture) {
      List&lt;PictureComment&gt; comments = commentDao.findVisibleByPicture(picture);
      Collections.sort(comments, new Comment.ByCreatedOnComparator(Comment.ByCreatedOnComparator.SORT_DESCENDING));
      return comments;
    }
    ...
  }
  
  @Controller
  @RequestMapping("/gallery/displayPicture.html")
  public class DisplayPictureController extends AbstractGalleryController {
  
    @RequestMapping(method = RequestMethod.GET)
    public String doGet(ModelMap model, @RequestParam(REQUEST_PARAM_PICTURE_ID) Long pictureId) {
      Picture picture = galleryService.getPicture(pictureId);
      if (picture != null) {
        model.addAttribute("picture", picture);
        // Add comments
        model.addAttribute("comments", galleryService.getComments(picture));
      } else {
        LOGGER.warn(MessageFormat.format("Picture {0} not found.", pictureId));
        return ViewConstants.CONTENT_NOT_FOUND;
      }
      return ViewConstants.GALLERY_DISPLAY_PICTURE;
    }
    ...
  }
  </code></pre>
  
  <p>I switched on debug logging for org.springframework.transaction and noticed, that "Creating new transaction", "Opened new EntityManager", "Getting...", "Closing..." and "Committing transaction" is done for every call of a method in my service class. Even if those methods where called by one single method in my controller class. Here is an example of my log output:</p>
  
  <pre><code>2014-12-03 10:53:00,448 org.springframework.transaction.support.AbstractPlatformTransactionManager getTransaction
  DEBUG: Creating new transaction with name [de.domain.webapp.gallery.service.GalleryServiceImpl.getPicture]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
  2014-12-03 10:53:00,448 org.springframework.orm.jpa.JpaTransactionManager doBegin
  DEBUG: Opened new EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@6133a72f] for JPA transaction
  2014-12-03 10:53:00,468 org.springframework.orm.jpa.JpaTransactionManager doBegin
  DEBUG: Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@5182c1b7]
  2014-12-03 10:53:00,468 org.springframework.transaction.interceptor.TransactionAspectSupport prepareTransactionInfo
  TRACE: Getting transaction for [de.domain.webapp.gallery.service.GalleryServiceImpl.getPicture]
  2014-12-03 10:53:00,489 org.springframework.transaction.interceptor.TransactionAspectSupport commitTransactionAfterReturning
  TRACE: Completing transaction for [de.domain.webapp.gallery.service.GalleryServiceImpl.getPicture]
  2014-12-03 10:53:00,489 org.springframework.transaction.support.AbstractPlatformTransactionManager processCommit
  DEBUG: Initiating transaction commit
  2014-12-03 10:53:00,489 org.springframework.orm.jpa.JpaTransactionManager doCommit
  DEBUG: Committing JPA transaction on EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@6133a72f]
  2014-12-03 10:53:00,489 org.springframework.orm.jpa.JpaTransactionManager doCleanupAfterCompletion
  DEBUG: Closing JPA EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@6133a72f] after transaction
  2014-12-03 10:53:00,489 org.springframework.orm.jpa.EntityManagerFactoryUtils closeEntityManager
  DEBUG: Closing JPA EntityManager
  </code></pre>
  
  <p>I know that I can use an OpenSessionInView to hold the hibernate session for a complete request but some people said, OSIV is an antipattern. Instead I'm using SpringOpenEntityManagerInViewFilter. But with no success. How can I achieve, Spring uses a single transaction for multiple service layer method calls of my controller? Or did I missunderstand anything?</p>
  
  <p>Here a part of my Spring configuration:</p>
  
  <pre><code>&lt;bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&gt;
      &lt;property name="dataSource" ref="dataSource" /&gt;
      &lt;property name="jpaVendorAdapter"&gt;
          &lt;bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"&gt;
              &lt;property name="database" value="MYSQL" /&gt;
              &lt;property name="showSql" value="false" /&gt;
          &lt;/bean&gt;
      &lt;/property&gt;
  &lt;/bean&gt;
  
  &lt;bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"&gt;
      &lt;property name="jndiName" value="java:comp/env/jdbc/tikron" /&gt;
  &lt;/bean&gt;
  
  &lt;bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /&gt;
  
  &lt;bean id="jpaTemplate" class="org.springframework.orm.jpa.JpaTemplate"&gt;
      &lt;property name="entityManagerFactory" ref="entityManagerFactory" /&gt;
  &lt;/bean&gt;
  
  &lt;bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"&gt;
      &lt;property name="entityManagerFactory" ref="entityManagerFactory" /&gt;
  &lt;/bean&gt;
  
  &lt;tx:annotation-driven transaction-manager="transactionManager" /&gt;
  
  &lt;context:component-scan base-package="de.domain.webapp"&gt;
      &lt;context:include-filter type="regex" expression=".*Service"/&gt;
  &lt;/context:component-scan&gt;
  </code></pre>
  
  <p>My persistence unit:</p>
  
  <pre><code>&lt;persistence-unit name="tikron-data" transaction-type="RESOURCE_LOCAL"&gt;
    &lt;!-- Entities located in external project tikron-data --&gt;
    &lt;jar-file&gt;/WEB-INF/lib/tikron-data-2.0.1-SNAPSHOT.jar&lt;/jar-file&gt;
    &lt;!-- Enable JPA 2 second level cache --&gt;
    &lt;shared-cache-mode&gt;ALL&lt;/shared-cache-mode&gt;
    &lt;properties&gt;
      &lt;property name="hibernate.hbm2ddl.auto" value="validate" /&gt;
      &lt;property name="hibernate.cache.use_second_level_cache" value="true" /&gt;
      &lt;property name="hibernate.cache.use_query_cache" value="true" /&gt;
      &lt;property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"/&gt;
      &lt;property name="hibernate.generate_statistics" value="false" /&gt; 
    &lt;/properties&gt;
  &lt;/persistence-unit&gt;
  </code></pre>
  
  <p>Some more log output from application startup:</p>
  
  <pre><code>2014-12-03 10:46:48,428 org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean createNativeEntityManagerFactory
  INFO: Building JPA container EntityManagerFactory for persistence unit 'tikron-data'
  2014-12-03 10:46:48,428 org.hibernate.ejb.HibernatePersistence logDeprecation
  WARN: HHH015016: Encountered a deprecated javax.persistence.spi.PersistenceProvider [org.hibernate.ejb.HibernatePersistence]; use [org.hibernate.jpa.HibernatePersistenceProvider] instead.
  2014-12-03 10:46:48,448 org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation
  INFO: HHH000204: Processing PersistenceUnitInfo [
      name: tikron-data
      ...]
  
  ...
  
  2014-12-03 10:46:51,101 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
  INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6cccf90d: defining beans [propertyConfigurer,messageSource,entityManagerFactory,dataSource]; root of factory hierarchy
  2014-12-03 10:46:51,111 org.springframework.web.context.ContextLoader initWebApplicationContext
  INFO: Root WebApplicationContext: initialization completed in 3374 ms
  </code></pre>
  
  <p>Thanks in advance.</p>