[
http://opensource.atlassian.com/projects/hibernate/browse/HHH-1523?page=c...
]
Martijn van Tilburg commented on HHH-1523:
------------------------------------------
We run into this issue as well in an EJB3 project. We use:
JBoss AS 4.2.0 as application server
Hibernate 3.2.3.ga as JPA entity manager
JBossCache 1.4.1.SP3 as second level cache
We use annotations to define our mappings, example:
[code]
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
...
@Entity
@Cache(usage=CacheConcurrencyStrategy.TRANSACTIONAL)
@Table(name =
"user",uniqueConstraints={@UniqueConstraint(columnNames={"name"})})
public class User extends BaseValueObject {
...
@ManyToMany (fetch=FetchType.LAZY)
@Cache(usage=CacheConcurrencyStrategy.TRANSACTIONAL)
public Set<Right> getRights() {
return rights;
}
...
}
[/code]
NOTE: The 'Right' entity also has the @Cache annotation applied.
Sometimes we want to fetch the 'Right' collection of 'User' but sometimes
not, example EJBQL with fetching:
[code]
import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
...
@Stateless
@Local( { IConfigHelperBean.class })
public class ConfigHelperBean implements IConfigHelperBean {
@PersistenceContext(unitName = "sampleApp")
private EntityManager em;
public User getUserByNameWithFetchJoin(String userName) {
return em.createQuery("SELECT u FROM User u LEFT JOIN FETCH u.rights WHERE
user.name = :userName").setParameter("userName",
userName).setHint("org.hibernate.cacheable", new
Boolean(true)).getSingleResult();
}
}
[/code]
The caching of the entities and the query seems to work correctly until we try to touch
the user.rights collection after the EJB transaction has ended (and thus the EntityManager
session is closed). We then are presented with the familiar LazyInitializationException as
thrown by the PersistentSet implementation. This only happens when the query is executed
for the second time and its results are in the second level cache (which we verified by
inspecting the cache with the JBossCache MBean that is deployed in our JBoss AS). If we
touch the 'rights' collection (by invoking its 'size' method) before the
EJB transaction ends the LazyInitializationException is not thrown anymore. The MySql
server log indicates no SQL queries are invoked anymore, this proves the second level
cache works as it should.
Recently the following was posted on the
hibernate.org main page
"28.04.2008 - Hibernate Core 3.3.0.CR1
This new release features:
* a redesign of the "second level cache" SPI
* a new integration with JBossCache 2.x taking full advantage of this new SPI
(special thanks to Brian Stansberry for his help and hard work on this)
* introduction of the org.hibernate.jdbc.Work API for performing JDBC work without
interfering with connection release modes
Additionally, this is the first release done from the new Maven project structure. The
Maven artifacts are deployed to the JBoss Maven repository under the groupId
org.hibernate. We also do still build a distribution bundle and upload it to SourceForge
here."
Is there any hope Hibernate 3.3.0 will solve this longstanding major bug?
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....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira