I have been trying for a number of weeks to solve this, and after reading everything available I still have no real answer so i hope this forum will help.
My problem is simple I have a small inheritance heirarchy and I am trying to execute a named native query to return a result set of these classes.
First the SqlResultSetMapping
@SqlResultSetMappings ( {@SqlResultSetMapping (name = "partyByKeywordsMapping" ,entities = { @EntityResult (entityClass=com.istana.corporal.fixture.jpa.JpaParty.class ,fields= {@FieldResult(name="m_oid", column="oid") ,@FieldResult(name="m_merged", column="merged_oid") } ,discriminatorColumn="clazz_" ) } ) } )
Q1 - the discriminatorColumn must be an integer value other wise an exception is thrown indicating that the column is not an integer. Even though the actual discriminator column in the database is a varchar().
Ok so I created a 'normal' query and executed it to capture the generated hibernate sql which I then formatted as a named native query as follows.
@NamedNativeQuery (name = "partyByKeywords" ,query = " select party_0.oid as oid " + ",party_0.merged_oid as merged_oid " + ",party_0.otype as oty " + ",case " + "when human_0.oid is not null then 1 " + "when legal_0.oid is not null then 2 " + "when party_0.oid is not null then 0 " + " end as clazz_ " + "from istana.corporal_party party_0 " + "join istana.corporal_party_keyword pkw_0 on party_0.oid=pkw_0.oid " + "left outer join istana.corporal_person human_0 on party_0.oid=human_0.oid " + "left outer join istana.corporal_legal legal_0 on party_0.oid=legal_0.oid " + "where pkw_0.keyword in (:kwd) " ,resultSetMapping = "partyByKeywordsMapping" )
You notice the case statement in the middle of the sql which acts as a discriminator column for the SqlResultSetMapping, this seems to be the hibernate method of distinguishing which class to create.
While everything runs it is not correct because the class returned from the query is one of the derived classes of the base class JpaParty, however it is not the correct derived class for the database row.
Q2 How does an integer value get mapped to the underlying class? I assume deep in the hibernate internals this occurs. Somewhere a map from 0,1,2 occurs to identify JpaParty, JpaPerson, JpaLegal but where and how?
So my classes (I will only post the header portion as this is about entity(s) the columns seem to work ok.
@Entity (name="CorporalParty") @Table (name="corporal_party", schema="istana") @Inheritance (strategy=InheritanceType.JOINED) @DiscriminatorColumn (name="otype", discriminatorType=DiscriminatorType.STRING,length=256) abstract public class JpaParty implements Party, Serializable
Derived class One
@Entity (name="CorporalLegal") @Table (name="corporal_legal", schema="istana") @DiscriminatorValue ("com.istana.corporal.fixture.jpa.JpaLegal") public class JpaLegal extends JpaParty implements Legal, Serializable
Derived class Two
@Entity (name="CorporalPerson") @Table (name="corporal_person", schema="istana") @DiscriminatorValue ("com.istana.corporal.fixture.jpa.JpaPerson") public class JpaPerson extends JpaParty implements Person, Serializable
As you can see I am using the class name as the discriminator value and this column is not used, and cannot be used, as the discriminator column of the named native query - instead the case statement acts in this capacity.
I have tried using all classes as entity results and I get an exception saying that there can only be one class for a TypedQuery. Ok so I then reduced this to the single EntityResult you see. I have tried changing the returned value from the discriminator column in the case statement regardless of the value returned the result is always an instanceof JpaLegal which (in this case) is always wrong as the only candidates for this query are JpaPerson instances. In fact the returned values of JpaLega actually have the details of the expected JpaPerson instances - this only works because I assume because there are no additional properties as yet.
So in closing how does the discriminator column map to the real values and does anyone have a complete accurate example. I have looked at many postings over the last 2-3 weeks and I have found none that are complete and work and certainly none that go beyond the simplest usage.
|