Hello I've run into a snag. It's not clear to me if it's a problem with Hibernate or a problem with the way I'm using it. Essentially Hibernate is not using the discriminator where I would expect it to.
Vital stats:
Hibernate Version 2.1.8
DB: Oracle 9 (thin driver)
Here is the mapping for our Test type. Test is abstract with two contrete subclasses, CrossCheckTest and UniquenessConstraint:
<class name="form.Test" table="TEST_TABLE">
<id name="id" type="long">
<generator class="native"/>
</id>
<discriminator column="type" type="string" not-null="true"/>
<property name="required" type="boolean" not-null="true"/>
<subclass name="com.rhoworld.edc.model.form.CrossCheckTest" discriminator-value="C">
<property name="name" type="string"/>
<many-to-one name="event" class="base.DataEvent" column="event_id"/>
</subclass>
<subclass name="base.RealDataEvent$UniquenessConstraint" discriminator-value="U">
<many-to-one name="event" class="base.RealDataEvent" column="event_id" not-null="true"/>
<property name="label" type="string"/>
<property name="strict" type="boolean"/>
<set name="ifields" table="UNIQUE_TEST_IFIELDS_TABLE" lazy="false">
<key column="uniqueness_constraint_id"/>
<many-to-many class="form.IField" column="ifield_id"/>
</set>
</subclass>
</class>
Both types of tests can be children of RealDataEvent, defined here:
<class name="base.Event" table="EVENT_TABLE">
<id name="id" type="long">
<generator class="native"/>
</id>
<discriminator column="type" type="string" not-null="true"/>
<property name="name" type="string" not-null="true"/>
<subclass name="base.DataEvent">
<property name="createLabel" type="string"/>
<subclass name="base.VirtualDataEvent" discriminator-value="V">
<many-to-one name="realEvent" class="base.RealDataEvent" column="real_event_id"/>
</subclass>
<subclass name="base.RealDataEvent" discriminator-value="D">
<property name="label" type="string"/>
<map name="crossCheckTests" inverse="true" lazy="true" cascade="all-delete-orphan" order-by="offset, name">
<key column="event_id"/>
<index column="name" type="string"/>
<one-to-many class="form.CrossCheckTest"/>
</map>
<set name="uniquenessConstraints" inverse="true" lazy="true" cascade="all-delete-orphan">
<key column="event_id"/>
<one-to-many class="base.RealDataEvent$UniquenessConstraint"/>
</set>
</subclass>
</subclass>
</class>
(Many irrelevant properties have been removed in order to focus on critical bits in above mapping doc.)
A call to RealDataEvent.getCrossCheckTests() generates the following SQL (whitespace added for readability):
select crosscheck0_.event_id as event_id__,
crosscheck0_.id as id__,
crosscheck0_.name as name__,
crosscheck0_.id as id0_,
crosscheck0_.expr as expr0_,
crosscheck0_.error as error0_,
crosscheck0_.contextPath as contextP8_0_,
crosscheck0_.name as name0_,
crosscheck0_.offset as offset0_,
crosscheck0_.event_id as event_id0_,
crosscheck0_.required as required0_
from TEST_TABLE crosscheck0_
where crosscheck0_.event_id=?
order by crosscheck0_.offset, crosscheck0_.name
I have determined that the reason my code is breaking is this query is returning both UniquenessConstraints and CrossCheckTests. I'm somewhat surprised looking at the "where" clause since I would have epxected for the discriminator to be there, ie:
where crosscheck0_.event_id=? and crosscheck0_.type='C'
I'm fairly certain including the discriminator in the query would fix my woes. Is there some reason why this isn't discriminating in the way I expect. Have I done something wrong in my mapping document?
Thanks for your help. Included below is a stack trace illustrating where my code breaks, although I'm pretty sure above is the culprit.
Thank you for your help,
Chris
15:02:29,640 ERROR net.sf.hibernate.collection.PersistentCollection:198 - Failed
to lazily initialize a collection
net.sf.hibernate.HibernateException: null index column for collection: com.rhowo
rld.edc.model.base.RealDataEvent.crossCheckTests
at net.sf.hibernate.collection.AbstractCollectionPersister.readIndex(Abs
tractCollectionPersister.java:368)
at net.sf.hibernate.collection.Map.readFrom(Map.java:201)
at net.sf.hibernate.loader.Loader.readCollectionElement(Loader.java:380)
at net.sf.hibernate.loader.Loader.getRowFromResultSet(Loader.java:235)
at net.sf.hibernate.loader.Loader.doQuery(Loader.java:281)
at net.sf.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections
(Loader.java:133)
at net.sf.hibernate.loader.Loader.loadCollection(Loader.java:990)
at net.sf.hibernate.loader.Loader.loadCollection(Loader.java:965)
at net.sf.hibernate.loader.OneToManyLoader.initialize(OneToManyLoader.ja
va:93)
at net.sf.hibernate.collection.AbstractCollectionPersister.initialize(Ab
stractCollectionPersister.java:284)
at net.sf.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.ja
va:3268)
at net.sf.hibernate.collection.PersistentCollection.initialize(Persisten
tCollection.java:195)
at net.sf.hibernate.collection.PersistentCollection.read(PersistentColle
ction.java:71)
at net.sf.hibernate.collection.Map.entrySet(Map.java:174)
at com.rhoworld.edc.controller.request.editor.PanelUpdater.applyCrossChe
cksTests(PanelUpdater.java:278)
|