-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Polymorphic HQL results in a faulty SQL statement
PostPosted: Thu May 18, 2006 9:27 am 
Newbie

Joined: Thu Oct 02, 2003 2:57 pm
Posts: 9
Location: Sweden
I have a problem with a polymorhic HQL query that produces a SQL query that is missing a term I would have thought should be there.

The classes involved in my problem Customer, PersonCustomer and CompanyCustomer. My customer (I'm a consultant) have determined that they need to have this separation.

Excerpt of mapping files involved:

Code:
<class name="CUstomer" table="customer">
   <id name="id" unsaved-value="0" column="customer_id">
      <generator class="native"/>
   </id>
   <discriminator column="class"/>
   <property name="address"/>
   ...
   ...
</class>

<subclass name="CompanyCustomer" lazy="false" extends="Customer" discriminator-value="COMPANY">

      <property name="companyname" />
   ...

      <property name="name" formula="companyname"/>

</subclass>

<subclass name="PersonCustomer" lazy="false" extends="Customer" discriminator-value="PERSON">

      <property name="firstname" />
      <property name="lastname" />
   ...

      <property name="name" formula="firstname || ' ' || lastname"/>

</subclass>


I have a HQL query that is supposed search based on the name. It looks like this:

FROM Customer customer WHERE UPPER(customer.name) LIKE :name

where :name is set to '%COMPANY1%, '%PERSONA%', etc.

This results in the following SQL statement:

Code:
select
   distinct customer0_.customer_id as customer1_0_, customer0_.address as address0_, customer0_.companyname as company20_0_, customer0_.firstname as firstname0_, customer0_.lastname as lastname0_, customer0_.compnayname as formula0_, customer0_.firstname || ' ' || customer0_.lastname as formula1_, customer0_.class as class0_
from
   ingivare customer0_
where
   (upper(customer0_.firstname || ' ' || customer0_.lastname) like '%COMPANY%')


As you probably can tell, when I search for COMPANY I get no results when it is only compared to firstname and lastname since those are only set on the PersonCustomer. If I manually run the query and add an entry for the companyname in the where clause I get the expected results.
What I am missing? Anybody see a better way to do this?

The names of the properties and classes have been translated for it to make sense to english speaking people so if I made a spelling mistake please overlook them, that is not why it is not working. I get no exceptions or errors, the debug output shows no strange entries, the only problem is I get no results when searching. And to me, there is a bug in the outputted SQL, but I may be wrong.

As a side question, shouldn't the where clause of the SQL end up using the formula0_ and the the formula1_ instead of the translated output?

Hibernate version: 3.1.3
Mysql 4.1


Top
 Profile  
 
 Post subject: Very similar possible bug using joined-subclasses as well
PostPosted: Fri May 19, 2006 11:48 am 
Newbie

Joined: Tue Dec 13, 2005 10:00 pm
Posts: 7
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


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.