title: LazyInitializationException in JPA and Hibernate
body: <p>I know that this question has been ask numerous times here and across the internet and I have read through many of those answers but I still don't understand the proper way to solve this problem. I am experimenting with Spring MVC and JPA and every time I access a lazily loaded property I get a LazyInitializationException. </p>
  
  <p>Here is some of the code I am experimenting with:</p>
  
  <pre><code>@Repository
  public class MyDAO {
      private static final Logger logger = LoggerFactory.getLogger(MyDAO.class);
  
      @PersistenceContext
      private EntityManager em;
  
      @Transactional
      public void logDOI() {
          DOI myDOI = em.find(DOI.class, Long.valueOf(1));
  
          // This line gives the expected output
          logger.info("Fetched DOI: " + myDOI.getDoiKey());
  
          // This line throws the LazyInitalizationException
          for(DOIMembership m : myDOI.getDoiMemberships()) {
              logger.info("Got DOI Membership id: " + m.getId());
          }
      }
  }
  </code></pre>
  
  <p>The entity I am accessing:</p>
  
  <pre><code>@Entity
  @Table(name="DOI")
  public class DOI implements Serializable {
      private static final long serialVersionUID = 1L;
  
      @Id
      @SequenceGenerator(name="DOI_ID_GENERATOR", sequenceName="DOI_SEQ")
      @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="DOI_ID_GENERATOR")
      private long id;
  
      // Other properties omitted
  
      //bi-directional many-to-one association to DOIMembership
      @OneToMany(mappedBy="doi", fetch=FetchType.LAZY)
      private Set&lt;DOIMembership&gt; doiMemberships;
  
      public DOI() {
      }
  
      public long getId() {
          return this.id;
      }
  
      public void setId(long id) {
          this.id = id;
      }
  
      // Other Accessors Omitted
  
  }
  </code></pre>
  
  <p>The entity referenced from DOI</p>
  
  <pre><code>@Entity
  @Table(name="DOI_MEMBERSHIP")
  public class DOIMembership implements Serializable {
      private static final long serialVersionUID = 1L;
  
      @Id
      @SequenceGenerator(name="DOI_MEMBERSHIP_ID_GENERATOR", sequenceName="DOI_MEMBERSHIP_SEQ")
      @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="DOI_MEMBERSHIP_ID_GENERATOR")
      private long id;
  
      //bi-directional many-to-one association to DOI
      @ManyToOne(fetch=FetchType.LAZY)
      @JoinColumn(name="DOI_ID")
      private DOI doi;
  
      @Column(name="GROUP_ID")
      private BigDecimal groupId;
  
      @Column(name="DATA_SET")
      private BigDecimal dataSetId;
  
      public DOIMembership() {
      }
  
      public BigDecimal getGroupId() {
          return groupId;
      }
  
      public BigDecimal getDataSetId() {
          return dataSetId;
      }
  
      public void setDataSetId(BigDecimal dataSetId) {
          this.dataSetId = dataSetId;
      }
  
      public void setGroupId(BigDecimal groupId) {
          this.groupId = groupId;
      }
  
      public long getId() {
          return this.id;
      }
  
      public void setId(long id) {
          this.id = id;
      }
  
      public DOI getDoi() {
          return this.doi;
      }
  
      public void setDoi(DOI doi) {
          this.doi = doi;
      }
  
  }
  </code></pre>
  
  <p>The Spring MVC Controller:</p>
  
  <pre><code>@Controller
  @RequestMapping("/summary")
  public class DOISummaryController {
      @Autowired
      MyDAO myDAO;
  
      @RequestMapping()
      public String DOISummary() {
          myDAO.logDOI();
  
          return "home";
      }
  }
  </code></pre>
  
  <p>My Spring configuration:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:context="http://www.springframework.org/schema/context"
      xmlns:task="http://www.springframework.org/schema/task"
      xmlns:tx="http://www.springframework.org/schema/tx"
      xsi:schemaLocation="http://www.springframework.org/schema/tx
          http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
          http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
          http://www.springframework.org/schema/task
          http://www.springframework.org/schema/task/spring-task-3.0.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.1.xsd"&gt;
  
      &lt;!-- Root Context: defines shared resources visible to all other web components --&gt;
  
      &lt;context:property-placeholder location="WEB-INF/spring/root-context.properties, WEB-INF/spring/datasource-context.properties"  /&gt;
  
      &lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt;
          &lt;property name="driverClassName"&gt;
              &lt;value&gt;oracle.jdbc.driver.OracleDriver&lt;/value&gt;
          &lt;/property&gt;
          &lt;property name="url"&gt;
              &lt;value&gt;${Url}&lt;/value&gt;
          &lt;/property&gt;
          &lt;property name="username"&gt;
              &lt;value&gt;${Username}&lt;/value&gt;
          &lt;/property&gt;
          &lt;property name="password"&gt;
              &lt;value&gt;${Password}&lt;/value&gt;
          &lt;/property&gt;
      &lt;/bean&gt;
  
      &lt;bean id="emf" 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&gt;
          &lt;property name="packagesToScan" value="org.myorg.doi.domain" /&gt;
          &lt;property name="jpaProperties"&gt;
              &lt;props&gt;
                  &lt;prop key="hibernate.dialect"&gt;
                      org.hibernate.dialect.Oracle10gDialect
                  &lt;/prop&gt;
                  &lt;prop key="hibernate.max_fetch_depth"&gt;3&lt;/prop&gt;
                  &lt;prop key="hibernate.jdbc.fetch_size"&gt;50&lt;/prop&gt;
                  &lt;prop key="hibernate.jdbc.batch_size"&gt;10&lt;/prop&gt;
                  &lt;prop key="hibernate.show_sql"&gt;true&lt;/prop&gt;
              &lt;/props&gt;
          &lt;/property&gt;
      &lt;/bean&gt;
  
      &lt;bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"&gt;
          &lt;property name="entityManagerFactory" ref="emf" /&gt;
      &lt;/bean&gt;
  
      &lt;tx:annotation-driven transaction-manager="transactionManager" /&gt;
  
      &lt;context:annotation-config /&gt;
  
      &lt;task:annotation-driven /&gt;
  
      &lt;context:component-scan base-package="org.myorg.doi" /&gt;
  
  &lt;/beans&gt;
  </code></pre>
  
  <p>And a stack trace, as requested:</p>
  
  <pre><code>SEVERE: Servlet.service() for servlet [appServlet] in context with path [/DOI] threw exception [Request processing failed; nested exception is org.hibernate.LazyInitializationException: could not initialize proxy - no Session] with root cause
  org.hibernate.LazyInitializationException: could not initialize proxy - no Session
      at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:430)
      at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:121)
      at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:180)
      at org.myorg.doi.dao.MyDAO.logDOI(MyDAO.java:27)
      at org.myorg.doi.web.DOISummaryController.DOISummary(DOISummaryController.java:29)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
      at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
      at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
      at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
      at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
      at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
      at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
      at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
      at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
      at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
      at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
      at com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.traceNextValve(HttpRequestOperationCollectionValve.java:116)
      at com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.invoke(HttpRequestOperationCollectionValve.java:98)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
      at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001)
      at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
      at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
      at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
      at java.lang.Thread.run(Thread.java:680)
  </code></pre>
  
  <p>I you can see, I am trying to use pure JPA and only using Hibernate as a JPA provider.</p>
  
  <p>I understand that the exception is caused by the session being detached from the entity. But, I thought that wouldn't happen if we are currently in a transaction, which should be the case since the logDOI method is annotated with @Transactional.</p>
  
  <p>Of course, everything works perfectly if I change the FetchType to EAGER but it seems that I shouldn't have to do that.</p>
  
  <p>I am also aware of OpenEntityManagerInViewFilter but it seems that I shouldn't have to use that either if I keep all access to my entities in a DAO annotated with @Transactional (or through some other means that I'm not aware of).</p>
  
  <p>I think that I might be approaching this problem incorrectly but I don't know what the correct approach is. How is one supposed to effectively use lazily loaded properties?</p>