Having a very similar problem with Hibernate 3.1.3 and joined-subclass queries. DB is Oracle using 9i dialect
An example hierarchy. Getters/Setters removed
Code:
public class a {
private b theb;
}
public abstract class b{
}
public class b1 extends b{
private String foo;
}
public class b2 extends b{
private String foo;
}
public class b3 extends b{
private String foo2;
}
Mapping file
<class name="a" table="A">
<id name="id" type="string" column="aId"/>
<many-to-one name="theb" column="b_fk" class="b" />
</class>
<class name="b" table="B">
<id name="id" type="string" column="bId"/>
</class>
<joined-subclass name="b1" table="B1" extends="b" >
<key column="b_fk" />
<property name="foo" column="foo"/>
</joined-subclass>
<joined-subclass name="b2" table="B2" extends="b" >
<key column="b_fk" />
<property name="foo" column="foo"/>
</joined-subclass>
<joined-subclass name="b3" table="B3" extends="b" >
<key column="b_fk" />
<property name="foo2" column="foo2"/>
</joined-subclass>
The problem is the B1 and B2's foo property that doesnt exist in B3. This HQL query
Code:
from a thea
join thea.theb b
where b.foo= 'hio'
produces SQL that only selects from B1, even though B2 would be valid.
Code:
select
a0_.aId as aId872_0_,
b1_.bId as bId873_1_,
a0_.b_fk as b2_872_0_,
b1_1_.foo as foo874_1_,
b1_2_.foo as foo875_1_,
b1_3_.foo2 as foo2_876_1_,
case
when b1_1_.b_fk is not null then 1
when b1_2_.b_fk is not null then 2
when b1_3_.b_fk is not null then 3
when b1_.bId is not null then 0
end as clazz_1_
from
A a0_
inner join
B b1_
on a0_.b_fk=b1_.bId
left outer join
B1 b1_1_
on b1_.bId=b1_1_.b_fk
left outer join
B2 b1_2_
on b1_.bId=b1_2_.b_fk
left outer join
B3 b1_3_
on b1_.bId=b1_3_.b_fk
where
b1_1_.foo='hio'
It seems that HQL parser finds the first property that matches the path b.foo and uses that.
If I attempt to specify the class directly with this
Code:
from a a
join a.theb b
where b.foo= 'hio'
and a.theb.class = b2
I get invalid resulting sql -- note that the where is still B1, but only is selecting B2
Code:
select
a0_.aId as aId872_0_,
b1_.bId as bId873_1_,
a0_.b_fk as b2_872_0_,
b1_1_.foo as foo874_1_,
b1_2_.foo as foo875_1_,
b1_3_.foo2 as foo2_876_1_,
case
when b1_1_.b_fk is not null then 1
when b1_2_.b_fk is not null then 2
when b1_3_.b_fk is not null then 3
when b1_.bId is not null then 0
end as clazz_1_
from
A a0_
inner join
B b1_
on a0_.b_fk=b1_.bId
left outer join
B1 b1_1_
on b1_.bId=b1_1_.b_fk
left outer join
B2 b1_2_
on b1_.bId=b1_2_.b_fk
left outer join
B3 b1_3_
on b1_.bId=b1_3_.b_fk
where
b1_1_.foo='hio'
and case
when b1_1_.b_fk is not null then 1
when b1_2_.b_fk is not null then 2
when b1_3_.b_fk is not null then 3
when b1_.bId is not null then 0
end=2
The only HQL that will give what I need is by manually joining the specific subclass
Code:
from a a, b2 b2
join a.theb b
where b2.foo= 'hio'
and a.theb = b2
which results in mostly correct query. It has wasteful left outer joins
Code:
select
a0_.aId as aId872_0_,
b2_.bId as bId873_1_,
b2x1_.b_fk as bId873_2_,
a0_.b_fk as b2_872_0_,
b2_1_.foo as foo874_1_,
b2_2_.foo as foo875_1_,
b2_3_.foo2 as foo2_876_1_,
case
when b2_1_.b_fk is not null then 1
when b2_2_.b_fk is not null then 2
when b2_3_.b_fk is not null then 3
when b2_.bId is not null then 0
end as clazz_1_,
b2x1_.foo as foo875_2_
from
A a0_
inner join
B b2_
on a0_.b_fk=b2_.bId
left outer join
B1 b2_1_
on b2_.bId=b2_1_.b_fk
left outer join
B2 b2_2_
on b2_.bId=b2_2_.b_fk
left outer join
B3 b2_3_
on b2_.bId=b2_3_.b_fk,
B2 b2x1_
inner join
B b2x1_1_
on b2x1_.b_fk=b2x1_1_.bId
where
b2x1_.foo='hio'
and a0_.b_fk=b2x1_.b_fk