NPE when lazy=false in joined-subclass?
code6226 Jun 25, 2010 12:15 PMI'm trying to add Envers to an existing project with Hibernate 3.5.2 and Spring. Hibernate is configured with mappings, and the annotations are basically limited to me just adding @Entity and @Audited over the various classes. Everything is audited into the database properly (as far as I can tell).
My problem is that a NPE occurs when I try to use getAuditReader().find(...) on a joined-subclass Entity that is set to lazy=false.
root cause
java.lang.NullPointerException
org.hibernate.tuple.entity.AbstractEntityTuplizer.createProxy(AbstractEntityTuplizer.java:634)
org.hibernate.persister.entity.AbstractEntityPersister.createProxy(AbstractEntityPersister.java:3713)
org.hibernate.envers.entities.mapper.relation.ToOneIdMapper.mapToEntityFromMap(ToOneIdMapper.java:90)
org.hibernate.envers.entities.mapper.MultiPropertyMapper.mapToEntityFromMap(MultiPropertyMapper.java:118)
org.hibernate.envers.entities.mapper.SubclassPropertyMapper.mapToEntityFromMap(SubclassPropertyMapper.java:67)
org.hibernate.envers.entities.EntityInstantiator.createInstanceFromVersionsEntity(EntityInstantiator.java:93)
org.hibernate.envers.entities.EntityInstantiator.addInstancesFromVersionsEntities(EntityInstantiator.java:103)
org.hibernate.envers.query.impl.EntitiesAtRevisionQuery.list(EntitiesAtRevisionQuery.java:90)
org.hibernate.envers.query.impl.AbstractAuditQuery.getSingleResult(AbstractAuditQuery.java:105)
org.hibernate.envers.reader.AuditReaderImpl.find(AuditReaderImpl.java:106)
MY.APP.persistence.dao.HistoryDAOImpl.getAllBBChangesets(HistoryDAOImpl.java:93)
This problem goes away when I set lazy=true for that Entity in the hibernate mapping, and I can retrieve the Entity just fine, and even then read its attributes and children. Unfortunately our project wasn't designed to support lazy=true in other, unrelated, parts of the code, so setting lazy=true is not really an option.
Here's a trimmed version of our mapping. The Entity that I'm having this problem with is "BusinessProcess", which is a joined-subclass of "BuildingBlock":
<class name="BuildingBlock" table="BB" lazy="true"> <id name="id" column="ID" type="java.lang.Integer"> <generator /> </id> <version name="olVersion" column="VERSION" type="integer" unsaved-value="negative" /> <many-to-one name="buildingBlockType" column="ID_BBT" not-null="true" /> <set name="owningUserEntities" table="BB_UE" lazy="true"> <key column="ID_BB" /> <many-to-many column="ID_UE" fetch="join" /> </set> <set name="attributeValueAssignments" lazy="true" inverse="true" cascade="delete,save-update"> <key column="ID_BB" /> <one-to-many /> </set> ... ...[[MANY JOINED-SUBCLASSES HERE]... ... <joined-subclass name="BusinessProcess" table="BP" lazy="false"> <key column="ID_BB" /> <property name="name" column="NAME" length="255" not-null="true" unique="true" /> <property name="description" column="DESCRIPTION" length="4000" /> <set name="businessMappings" lazy="true" inverse="true" cascade="delete"> <key column="ID_BP" /> <one-to-many /> </set> <set name="businessDomains" table="BP_BD" lazy="true"> <key column="ID_BP" /> <many-to-many column="ID_BD" /> </set> <many-to-one name="parent" column="ID_PARENT" insert="true" update="true" /> <list name="children" lazy="true"> <key column="ID_PARENT" /> <list-index column="POS" /> <one-to-many /> </list> <property name="position" column="POS" type="integer" update="true" insert="true"/> </joined-subclass> ... </class>
Again, the NPE only occurs when the line, as above, reads:
<joined-subclass name="BusinessProcess" table="BP" lazy="false">
If I change it to the below, the NPE does not occur (but that's not really an option for this project, as I mentioned)
<joined-subclass name="BusinessProcess" table="BP" lazy="true">
The problem in the Hibernate code seems to be that proxyFactory is null. My issue seems very similar to bug HHH-3854, but I'm unsure, because the current mapping has worked just fine for us with just Hibernate. It's only when Envers tries to retrieve previous revisions of Entities that this issue occurs in our project.