Details
Description
When query against a class mapped on multiple joined tables (using "super"-references) or using such a class in a reference only objects of the base type class will be instantiated.
Example:
Employee<-Manager<-Shareholder
Criteria crit = new Criteria();
Query query = QueryFactory.newQuery(Employee.class, crit);
Collection result = broker.getCollectionByQuery(query);
Collection result only contains objects of type 'Employee' (the base class) even if the real type was Manager or Shareholder.
See in OJB test suite ...broker.InheritanceMultipleTableTest#testInheritancedObjectsInCollectionReferences.
The problem is how OJB is building the join when using super-references
("super" keyword in reference-descriptor).
In SqlQueryStatement there is no specific handling for queries against
classes mapped on multiple joined tables, thus always instances of the
query class (e.g. Employee) are returned instead of the real
sub-classes (e.g. Employee, Manager, ...).
A solution for this issue is to use sql-case
expressions to build the join:
(e.g. Manager and Customer are sub-classes of Employee)
select
person0_.person_id as person1_,
...
person0_1_.title as title1_,
...
person0_2_.bio as bio2_,
person0_3_.comments as comments3_,
person0_3_.salesperson as salesper3_3_,
case
when person0_2_.person_id is not null then 2
when person0_1_.person_id is not null then 1
when person0_3_.person_id is not null then 3
when person0_.person_id is not null then 0
end as clazz_
from Person person0_
left outer join Employee person0_1_ on
person0_.person_id=person0_1_.person_id
left outer join Manager person0_2_ on
person0_.person_id=person0_2_.person_id
left outer join Customer person0_3_ on
person0_.person_id=person0_3_.person_id
where (person0_2_.bio='my bio')
Now the application can decide which class to instantiate by evaluating the "clazz_" column in the ResultSet. This is the missing part in OJB (need improvements in org.apache.ojb.broker.accesslayer.sql.* classes and RsIterator).