1

I have a problem with only one controller that has a lazy loaded entity(there is a transaction initiated and commited, see stack trace)

17:56:46,084 DEBUG HibernateTransactionManager:438 - Found thread-bound Session [org.hibernate.impl.SessionImpl@6b204e88] for Hibernate transaction
17:56:46,085 DEBUG HibernateTransactionManager:471 - Participating in existing transaction
17:56:46,085 DEBUG HibernateTransactionManager:438 - Found thread-bound Session [org.hibernate.impl.SessionImpl@6b204e88] for Hibernate transaction
17:56:46,085 DEBUG HibernateTransactionManager:471 - Participating in existing transaction
Hibernate: select preference0_.id as id66_, preference0_.name as name66_, preference0_.value as value66_, preference0_.default_value as default4_66_, preference0_.updated_at as updated5_66_ from preferences preference0_ where preference0_.name='scheduleInterval'
17:56:46,086 DEBUG GooGooStatementCache:457 - cxnStmtMgr.statementSet( com.mysql.jdbc.JDBC4Connection@5ec60ee2 ).size(): 21
17:56:46,086 DEBUG GooGooStatementCache:196 - checkoutStatement: com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 111; checked out: 1; num connections: 10; num keys: 111
17:56:46,087 DEBUG GooGooStatementCache:271 - checkinStatement(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 111; checked out: 0; num connections: 10; num keys: 111
17:56:46,089 FATAL app:79 - service
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:167)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
    at com.model.User_$$_javassist_76.getName(User_$$_javassist_76.java)
    at com.model.json.ScheduleItemWrapper.wrap(ScheduleItemWrapper.java:55)
    at com.web.controllers.ajax.Model.wrap(Model.java:127)
    at com.web.controllers.ajax.Model.toJSON(Model.java:165)
    at com.web.controllers.ajax.Model.getContent(Model.java:51)
    at com.web.controllers.ajax.BasicAction.execute(BasicAction.java:27)
    at com.web.HibernateServlet.doService(HibernateServlet.java:113)
    at com.web.HibernateServlet.service(HibernateServlet.java:66)
    at sun.reflect.GeneratedMethodAccessor200.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:695)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
    at com.levitech.web.controllers.schedule.ScheduleList$$EnhancerByCGLIB$$4a7ae33e.service(<generated>)
    at com.levitech.web.RequestDispatcher.service(RequestDispatcher.java:63)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:662)
17:56:46,090 DEBUG HibernateTransactionManager:753 - Initiating transaction commit
17:56:46,090 DEBUG HibernateTransactionManager:653 - Committing Hibernate transaction on Session [org.hibernate.impl.SessionImpl@6b204e88]
17:56:46,091 DEBUG HibernateTransactionManager:735 - Closing Hibernate Session [org.hibernate.impl.SessionImpl@6b204e88] after transaction
17:56:46,091 DEBUG SessionFactoryUtils:800 - Closing Hibernate Session

The model (ScheduleItem and User) and their hibernate mappings

public class ScheduleItem {
  private Integer id;
  ....
  private User user;

}

public class User {
  private Integer id;
  ...
  private String name;

}

<class 
    name="ScheduleItem" 
    table="schedule_item"
>

    <cache usage="read-write"/>


    <id
        name="id"
        type="integer"
        column="id"
    >
    <generator class="identity" />
    </id>
    <many-to-one name="user" column="user_id" lazy="proxy"></many-to-one>
</class>

<class 
    name="ScheduleItem" 
    table="schedule_item"
>

    <cache usage="read-write"/>


    <id
        name="id"
        type="integer"
        column="id"
    >
    <generator class="identity" />
    </id>
    <property name="name" column="name" type="string" />
</class>

I found the culprit. OpenSessionViewFilter is using a different session or sessionfactory.

Here is my Spring config and web.xml (What am I doing wrong?):

Part of web.xml:

<filter>
      <filter-name>hibernateFilter</filter-name>
      <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
      <init-param>
         <param-name>sessionFactoryBeanName</param-name>
         <param-value>sessionFactory</param-value>         
      </init-param>      
   </filter>

   <filter-mapping>
     <filter-name>hibernateFilter</filter-name>
     <url-pattern>/app/s/*</url-pattern>
   </filter-mapping> 

Part of Spring Config:

<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
     <property name="driverClass" value="${db.driver}"/>
     <property name="jdbcUrl" value="${db.url}"/>
     <property name="user" value="${db.user}"/>
     <property name="password" value="${db.pass}"/>

       <!-- Pool properties -->
     <property name="minPoolSize" value="5" />
     <property name="maxPoolSize" value="100" />
     <property name="acquireIncrement" value="5" />
     <property name="maxStatements" value="200" />
     <property name="idleConnectionTestPeriod" value="120" />
     <property name="maxIdleTime" value="1800" />

  </bean>

      <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="myDataSource"></property>
         <property name="mappingLocations" value="classpath*:com/model/hbm/**/*.hbm.xml" />

    <property name="hibernateProperties">
      <value>
        hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
        hibernate.show_sql=true
        hibernate.cache.region.factory_class=net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory
        hibernate.cache.use_query_cache=true
        hibernate.cache.use_second_level_cache=true
      </value>
    </property>
      </bean>

      <bean id="transactionManager"
                class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
      </bean>

3 Answers 3

2

From the log it looks like the session is still open when you get this exception. The other scenario in which you would get such an exception is if the row doesn't exist in the database.

User user = session.load(User.class, 1000); // Create a proxy
user.getName(); // This would throw lazy initialization exception if row doesn't exist

One more scenario that can lead to this is working with detached objects. If you fetched and stored the ScheduleItem as a HTTPSession variable. Retrieve it in another request and then try to access the proxy - it will result in the same exception. The session that was used to load the object has been closed. If that is the case you need to first reattach the object to the new session (merge, update or lock) before using it.

Sign up to request clarification or add additional context in comments.

3 Comments

Interesting information but the association hibernate is trying to lazy load is null (the row is null) nothing needs to be loaded. ScheduleItem has other associations mapped many-to-one that are also null in the database and they are not giving problems. If I add fetch="join" lazy="false" for that particular association the problem goes away. I'm not using detached sessions..I have a session per request
Can you cross check, because it doesn't make sense. If the user_id column has a null value then the user reference in ScheduleItem should have been null - it shouldn't have created a proxy at all. From the stack trace that doesn't appear to be the case. Can you include the code for com.model.json.ScheduleItemWrapper.wrap.
Thank you for putting me in the right direction..I've had transaction management through aop on the service layer and a single transaction that required a propagation of "new", the transaction was committed before the request was complete (as expected) and a new session was opened
2

There are multiple solutions for your problem:

  • The easiest one is using Spring's OpenSessionInViewFilter. Just add this filter to your web.xml and configure it to filter your request. This filter opens and closes Hibernate session in a filter, so during page rendering session will be open.

  • Some people believe that OpenSessionInViewFilter is against good design, and it mixes business logic into presentation tier. If you think so, fetch the referenced object in your query (for example by using join fetch in your HQLs).

1 Comment

Can you write down your entities and the query?
-1

You could try to:

  • Eagerly load the collection.
  • initialize the collection before leaving the collection by calling the respective getter method Hibernate.initialize(rtn.getUserRoles());

Thats basically two times the same approach depending on what works best in your setup. You are making sure to load the complete entity before leaving the session that way the entity can be detached from the old and then reatached to a new session without problems. What you are doing is initializing the proxy before leaving the session so that the collection is available for sure when you are out of a session context.

2 Comments

Why would I want to expose my dao implementation by using Hibernate specific code in my service service or web layer? I could easily eagerly fetch the collection and avoid the issue but the whole point is that I do want to lazy load it on demand.
Well, then please specify the question with information about your transaction and session demarcation and the context in which the exception is thrown, since this is kinda necessary to give more advice than some blind tries. @theDownVoter: please state the reason for the vote so I can learn from my mistake?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.