Hi,
I need to use an Oracle index hint (can't avoid it) and so therefore need to use Native SQL rather than HQL. However, Hibernate does not seem to be able to figure out which subclass to instantiate based on the results.
Hibernate version: 3.2-rc5
What I have is abase HBM file 'Event', which 'XEvent' and 'YEvent' extend using a table per subclass hierarchy (<joined-subclass>).
Here is a dumbed down version of the mapping files. Please note that these persisted entities don't have POJOs, they're returned as Maps by Hibernate ('Dynamic Models', see
http://www.hibernate.org/hib_docs/refer ... amicmodels but I don't think this really plays a factor to this problem).
Mapping documents:
Event:
<hibernate-mapping>
<class entity-name="Event" table="EVENT">
<id name="id" type="java.lang.String" access="field">
<column name="EVENT_ID" length="36"/>
<generator class="assigned"/>
</id>
<version column="VERSION" name="version" type="java.lang.Long" access="field" unsaved-value="null"/>
<property name="eventType" type="java.lang.String">
<column name="EVENTTYPE" length="60" not-null="true"/>
</property>
.... SNIP ...
</class>
</hibernate-mapping>
XEvent:
<hibernate-mapping>
<joined-subclass entity-name="XEvent" table="XEVENT" extends="Event">
<key column="EVENT_ID"/>
</joined-subclass>
</hibernate-mapping>
YEvent:
<hibernate-mapping>
<joined-subclass entity-name="YEvent" table="YEVENT" extends="Event">
<key column="EVENT_ID"/>
<property access="field" name="someOtherColumnProperty" type="java.lang.String" not-null="false">
<column name="SOME_OTHER_COLUMN"/>
</property>
</joined-subclass>
</hibernate-mapping>
So, my native SQL query should be something like something like:
Code:
select Event.EVENT_ID, VERSION, EVENTTYPE , SOME_OTHER_COLUMN, ..., ..., from Event left outer join XEVENT on EVENT.EVENT_ID = XEVENT.EVENT_ID left outer join YEVENT on EVENT.EVENT_ID = YEVENT.EVENT_ID
And I do this to my SQLQuery: addEntity("Event"), which, according the the Native SQL chapter, is all that is required (declare the "root" entity). There's very little on how inheritance should be handled.
What happens when hibernate executes that? Well, it executes the query, and gets a result set, then tries to retrieve a "clazz_" column from this result set, which doesn't exist, and so an exception is thrown. Why does hibernate expect this to be in the result set when it knows it's using custom SQL?
I've looked into this clazz_ column and found that hibernate uses it as an inheritance discriminator so it knows what subclass to instantiate (i.e., XEvent or Yevent?).
If I was to do the following, it works fine:
Code:
select Event.EVENT_ID, VERSION, EVENTTYPE , SOME_OTHER_COLUMN, ..., ..., , case when XEVENT.EVENT_ID is not null then 1 when YEVENT.EVENT_ID is not null then 2 when EVENT.EVENT_ID is not null then 0 end as clazz_ from Event left outer join XEVENT on EVENT.EVENT_ID = XEVENT.EVENT_ID left outer join YEVENT on EVENT.EVENT_ID = YEVENT.EVENT_ID
As you can see, clazz_ is 0,1 or 2 based on the the entity type. I figured this out from looking at the SQL generated when using normal HQL. Why can't I just use this? Because the 0, 1 and 2 keys refer to Event, XEvent and YEvent, respectively, in some map, and there is no guarantee that some other time 1 will refer to XEvent and 2 refer to Yevent (could easily be the other way around).
Any advice on this issue? Is this a limitation or am I going about it the wrong way?
Thanks in advance,
Cormac