Hi Folks,
I have a schema that represents an online shop, where Products belong to exactly one Category, and each Category contains a collection of Products that belong to it. The Product table has a categoryid column, and the category - product mapping is carried out via a pivot table called 'category_products'.
A LazyInitializationException occurs when I try to get a Product from the database by id because, when constructing the Product instance, hibernate is calling Product's setCategory method, which is trying to add a reference to itself inside Category's 'products' collection, however the collection hasn't yet been initialized. I've tried adding lazy="false" to the mapping entry for the 'products' collection, but this didn't seem to have an effect. I've also tried enabling eager fetching on this collection (using outer-join="true") but this didn't work either.
I'm actually not keen on pulling all of the Products belonging to a particular Category out of the database when I only want to get 1 product from that Category, so perhaps I'm going about this in the wrong way.
Do you guys have any ideas?
Cheers,
Richard.
Hibernate version:
3.1.3
Mapping documents:
Category.hbm.xml
============
[...]
<set name="products" lazy="false" cascade="all-delete-orphan" table="category_products">
<key column="categoryid"/>
<many-to-many column="productid" class="uk.co.plugandplaydesign.core.dal.hibernate.Product"/>
</set>
[...]
Product.hbm.xml
===========
[...]
<many-to-one name="category" cascade="none" column="categoryid" class="uk.co.plugandplaydesign.core.dal.hibernate.Category"/>
[...]
Code between sessionFactory.openSession() and session.close():
Essentially, it's just creating and running this query -
HibernateUtil.currentSession(hibernateConfig).createQuery("from Product where id = '2'");
Here's the setCategory method in Product that's causing the trouble -
public void setCategory(Category category) {
if (this.category != null) {
//if the product already belongs to a category, remove
//the reference
this.category.getProducts().remove(this);
}
this.category = category;
if (this.category != null) {
category.getProducts().add(this); // (1)
}
}
// (1) the collection returned by category.getProducts() hasn't been
// initialized at this point for some reason
Full stack trace of any exception that occurs:
227-Dec-2006 10:56:05 org.hibernate.LazyInitializationException <init>
SEVERE: illegal access to loading collection
org.hibernate.LazyInitializationException: illegal access to loading collection
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:341)
at org.hibernate.collection.AbstractPersistentCollection.write(AbstractPersistentCollection.java:183)
at org.hibernate.collection.PersistentSet.add(PersistentSet.java:165)
at uk.co.plugandplaydesign.core.dal.hibernate.Product.setCategory(Product.java:211)
at sun.reflect.GeneratedMethodAccessor81.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:42)
at org.hibernate.tuple.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:330)
at org.hibernate.tuple.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:188)
at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:3232)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:129)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:842)
at org.hibernate.loader.Loader.doQuery(Loader.java:717)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.loadCollection(Loader.java:1919)
at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:36)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:520)
at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:60)
at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1676)
at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:454)
at org.hibernate.engine.StatefulPersistenceContext.initializeNonLazyCollections(StatefulPersistenceContext.java:755)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:229)
at org.hibernate.loader.Loader.doList(Loader.java:2145)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2029)
at org.hibernate.loader.Loader.list(Loader.java:2024)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:375)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:308)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:153)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1106)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
at uk.co.plugandplaydesign.core.dal.HibernateUtil.executeQuery(HibernateUtil.java:39)
at uk.co.plugandplaydesign.core.dal.HibernateUtil.executeQuery(HibernateUtil.java:44)
at uk.co.plugandplaydesign.core.dal.HibernateUtil.executeQuery(HibernateUtil.java:27)
at uk.co.plugandplaydesign.core.dal.PersistenceHandler.getEntities(PersistenceHandler.java:111)
at uk.co.plugandplaydesign.core.dal.PersistenceHandler.getSingleEntity(PersistenceHandler.java:94)
at uk.co.plugandplaydesign.core.dal.dao.ProductDAO.getShallowProduct(ProductDAO.java:184)
at uk.co.plugandplaydesign.core.dal.dao.ProductDAO.getProduct(ProductDAO.java:189)
at uk.co.plugandplaydesign.dal.dao.AbstractPersistenceTestFixture.tearDown(AbstractPersistenceTestFixture.java:185)
at uk.co.plugandplaydesign.dal.dao.ProductPersistenceTest.tearDown(ProductPersistenceTest.java:62)
at junit.framework.TestCase.runBare(TestCase.java:136)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:120)
at junit.framework.TestSuite.runTest(TestSuite.java:228)
at junit.framework.TestSuite.run(TestSuite.java:223)
at org.junit.internal.runners.OldTestClassRunner.run(OldTestClassRunner.java:35)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Name and version of the database you are using:
Postgres 8.1
|