I have the parent/child type relation for categories with the lazy initialization of the parentCategory and childCategories as default in the mapping file.
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="by.hibernate.app.model.Category" table="CATEGORY"> <id name="id" column="CATEGORY_ID"> <generator class="native"/> </id> <property name="name" column="NAME"/> <many-to-one name="parentCategory" class="by.hibernate.app.model.Category" column="PARENT_CATEGORY_ID" cascade="none"/> <set name="childCategories" table="CATEGORY" cascade="all" inverse="true" lazy="true"> <key column="PARENT_CATEGORY_ID"/> <one-to-many class="by.hibernate.app.model.Category"/> </set> </class> </hibernate-mapping>
Hibernate version: 3.1.3
I need to show all the categories on the page at once.
I tried to achive that with Criteria by setting FetchMode.JOIN as follows:
Criteria criteria = session.createCriteria(Category.class); criteria.setFetchMode("parentCategory", FetchMode.JOIN); criteria.setFetchMode("childCategories", FetchMode.JOIN); criteria.add(Expression.isNull("parentCategory")); Set categories = new HashSet(criteria.list());
I got parent categories with the collection of child categories. Unfortunately, each item in the childCategories collection has an uninitialized childCategories collection. I'll give an example:
+Auto - parent element --+Audi - child element ----+Audi 100 - child element ----+Audi 80 - child element --+Mazda - child element ----+Mazda 6 - child element ----+Mazda 3 - child element +Computres - parent element --+Dell - child element ----+Laptop - child element
I got collection of 2 elemnts: Auto and Computers with childCategories containing (Audi, Mazda) and (Dell) respectively. The problem is that the childCategories collection of the Audi, Mazda and Dell objects is uninitialized - throws LazyInitializationException.
I tried to do the same with HQL like:
Query query = session.createQuery("from Category c left join fetch c.parentCategory left join fetch c.childCategories where c.parentCategory is null"); Set categories = new HashSet(query.list());
and got the same result.
I found that I could set the lazy to false as default in the mapping :
<set name="childCategories" table="CATEGORY" cascade="all" inverse="true" lazy="false"> <key column="PARENT_CATEGORY_ID"/> <one-to-many class="by.hibernate.app.model.Category"/> </set>
and all started working without setFetchMode for the childCategories property:
Criteria criteria = session.createCriteria(Category.class); criteria.setFetchMode("parentCategory", FetchMode.JOIN); criteria.add(Expression.isNull("parentCategory")); Set categories = new HashSet(criteria.list());
However this approach can't be used because the lazy initialization is used in another usecases. Moreover, if lazy="false" is default, there is no way to set another fetch mode for Criteria, say FetchMode.SELECT (it seems to be a bug in Hibernate).
Any ideas how to resolve this issue?
|