[hibernate-issues] [Hibernate-JIRA] Commented: (HHH-1523) LazyInitializationError on enabling query cache...

Erik Innocent (JIRA) noreply at atlassian.com
Tue Dec 4 15:09:59 EST 2007


    [ http://opensource.atlassian.com/projects/hibernate/browse/HHH-1523?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_29050 ] 

Erik Innocent commented on HHH-1523:
------------------------------------

I've encountered this exact problem and can verify a workaround. The problem is covered well here:

http://www.sourcelabs.com/?page=kb&task=art&cat=12&selectedid=70

To quote it, the problem is characterized as:

[quote]
Hibernate incorrectly throws LazyInitializationException when all the following conditions are satisfied:

   1. a collection is mapped with lazy="true" or a single-valued association is mapped with lazy="proxy",
   2. the lazy mapping is overriden when querying the parent using a Criteria with fetch mode set to FetchMode.JOIN (or the deprecated FetchMode.EAGER) or using HQL with "left join fetch",
   3. the query cache is enabled and the query results are up-to-date,
   4. the collection/association is accessed outside the Hibernate Session in which the Criteria or HQL was executed.
[/quote]

The solution, which I also found at that link, is to make use of Hibernate.initialize(Object o) on each eagerly fetched association before the main object gets detached. Examples can be found at the link, though I was able to get by without resorting to those ugly transaction calls and their try-catches.

For the record, this is uncool and caused me to waste a few days, but I'm glad at least there's a straightforward and cheap workaround. Also, being happy to have it working at all, I haven't checked to see if the Hibernate.initialize(Object o) is in fact hitting the cache, or if it's calling through to the DB. I leave this as an exercise for the reader.

> LazyInitializationError on enabling query cache...
> --------------------------------------------------
>
>                 Key: HHH-1523
>                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1523
>             Project: Hibernate3
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 3.0.5, 3.1
>         Environment: 3.0.1 and 3.1, HSQLDB and Oracle
>            Reporter: Vikas Sasidharan
>         Attachments: cache_issue.log, QueryCacheIssue.zip
>
>
> I have two domain objects - Employee and Department - and there is a 1:N relationship from Department to Employee. When I join fetch an Employee with its Department, without query cache enabled, it works fine. If I enable query cache for this same query, it bombs with a LazyInitializationException. 
> Notes:
>   1) We get this error only if query cache is enabled.
>   2) We observed the same behaviour on both oscache and ehcache
>   3) Calling Hibernate.initialize() explicitly after firing the HQL seems to work. The initialization does not fire an extra query though (it seems to pick it from the cache).
>   4) Setting "lazy=false" on the "many-to-one" mapping also works. However, it wouldn't be acceptable.
> Hibernate version: 3.0.5 
> Mapping documents: 
> Employee.hbm.xml 
> <hibernate-mapping> 
>     <class name="tavant.platform.test.domain.Employee" 
>         table="CACHE_ISSUE_EMP" lazy="true"  dynamic-update="true" dynamic-insert="true"> 
>         <cache usage="read-write" /> 
>         <id name="id" column="EMP_ID" type="java.lang.Long" 
>        access="field" unsaved-value="null"> 
>             <generator class="increment" /> 
>         </id> 
>         
>         <property name="name" type="string" update="true" 
>             insert="true" column="EMP_NAME"/> 
>         <many-to-one name="department" class="tavant.platform.test.domain.Department" 
>             cascade="none" outer-join="auto" update="true" insert="true" column="DEPARTMENT_ID"/> 
>     </class> 
> </hibernate-mapping> 
>  
> Department.hbm.xml 
> <hibernate-mapping> 
>     <class name="tavant.platform.test.domain.Department" table="CACHE_ISSUE_DEP" 
>         lazy="true"  dynamic-update="true" dynamic-insert="true"> 
>         
>         <cache usage="read-write" /> 
>         <id name="id" column="DEPARTMENT_ID" 
>        type="java.lang.Long" access="field">            
>        <generator class="increment"/> 
>         </id> 
>         <property name="name" type="java.lang.String" 
>             update="false" insert="true" column="NAME"/> 
>         <bag name="employees" lazy="true" 
>             inverse="true" cascade="save-update" access="field"> 
>             <cache usage="read-write"/> 
>             <key column="DEPARTMENT_ID"/> 
>             <one-to-many class="tavant.platform.test.domain.Employee"/> 
>       </bag> 
>     </class> 
> </hibernate-mapping> 
>  
> Code between sessionFactory.openSession() and session.close(): 
>     public Employee getEmployeeWithDepartment(String empName) { 
>         Session session = null; 
>         try { 
>             session = sessionFactory.openSession(); 
>             Employee emp = (Employee) session.createQuery( 
>                             "from Employee e join fetch e.department where e.name = :name") 
>                             .setString("name", empName) 
>                             .setCacheable(true) 
>                             .uniqueResult(); 
>             // If I uncomment the next line, this works (even without 
>             // firing an extra query)! 
>             // Hibernate.initialize(emp.getDepartment()); 
>             return emp; 
>         } finally { 
>             if (session != null) { 
>                 session.close(); 
>             } 
>         } 
>     } 
>         
>         // First load employee and populate cahces 
>         Employee emp = test.getEmployeeWithDepartment(EMPLOYEE_NAME); 
>         System.out.println("Employee : " + emp + ", Employee.Department : " 
>                         + emp.getDepartment()); 
>         
>         // Now try to make use of the cache 
>         emp = test.getEmployeeWithDepartment(EMPLOYEE_NAME); 
>         System.out.println("Employee : " + emp + ", Employee.Department : " 
>                         + emp.getDepartment());        
>  
> Full stack trace of any exception that occurs: 
> org.hibernate.LazyInitializationException: could not initialize proxy - the owning Session was closed
> 	at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:53)
> 	at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:84)
> 	at org.hibernate.proxy.CGLIBLazyInitializer.intercept(CGLIBLazyInitializer.java:134)
> 	at tavant.platform.test.domain.Department$$EnhancerByCGLIB$$67b26899.toString(<generated>)
> 	at java.lang.String.valueOf(String.java:2131)
> 	at java.lang.StringBuffer.append(StringBuffer.java:370)
> 	at tavant.platform.test.client.TestPrefetchRelationWithQueryCacheEnabled.main(TestPrefetchRelationWithQueryCacheEnabled.java:116)
>  
> Name and version of the database you are using: 
> We have noticed this on Oracle and HSQL 
> The generated SQL (show_sql=true): 
> #First read, goes fine 
> Hibernate: select employee0_.EMP_ID as EMP1_0_, department1_.DEPARTMENT_ID as DEPARTMENT1_1_, employee0_.EMP_NAME as EMP2_1_0_, employee0_.DEPARTMENT_ID as DEPARTMENT3_1_0_, department1_.NAME as NAME0_1_ from CACHE_ISSUE_EMP employee0_ inner join CACHE_ISSUE_DEP department1_ on employee0_.DEPARTMENT_ID=department1_.DEPARTMENT_ID where (employee0_.EMP_NAME=? ) 
> #Prints the Employee and Department fine 
> Employee : [Id : 1, name : testEmployee], Employee.Department : [Id : 1, name : testDepartment] 
> #Second read bombs! 
> org.hibernate.LazyInitializationException: could not initialize proxy - the owning Session was closed
> 	at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:53)
> 	at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:84)
> 	at org.hibernate.proxy.CGLIBLazyInitializer.intercept(CGLIBLazyInitializer.java:134)
> 	[..]
> Please have a look at the post [http://forum.hibernate.org/viewtopic.php?t=955839] for more details and follow ups.
> Kindly help.  I am attaching an Eclipse Project containing the TestCase. The main file is TestPrefetchRelationWithQueryCacheEnabled.
> Thanks,
> Vikas

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        



More information about the hibernate-issues mailing list