-->
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.  [ 6 posts ] 
Author Message
 Post subject: Left joining tables with composite-id and discriminator
PostPosted: Sat Sep 04, 2004 10:05 pm 
Newbie

Joined: Thu Sep 02, 2004 4:19 am
Posts: 4
Location: Bergen - Norway
Hi,

I have the following tables in a database:
Code:
      ------------------      -------------------     
      | tbl_locations  |      | tbl_site_status |     
      |----------------|      |-----------------|     
      | loc_id (pk)    |      | ss_site_id(pk)  |     
      | loc_name       |      | ss_type(pk)     |     
      ------------------      | ss_from(pk)     |     
                              | ss_to           |         
                              | ss_status       |
                              -------------------
where ss_site_id is foreign key to tbl_locations if ss_type = "2"
     

Sample data in tbl_site_status
+------------+---------+------------+------------+-----------+
| ss_iste_id | ss_type | ss_from    | ss_to      | ss_status |
+------------+---------+------------+------------+-----------+
|          1 |       1 | 2003-01-01 | 2003-12-31 |         3 |
|          2 |       2 | 2003-01-01 | 2003-12-31 |         0 |
|          2 |       2 | 2004-01-01 | NULL       |         1 |
|          3 |       2 | 2003-01-01 | NULL       |         0 |
+------------+---------+------------+------------+-----------+



I Want to transform the following query into Hibernate syntax:
Code:
   "select * from tbl_locations
    left join tbl_site_status on ss_site_id = loc_id and ss_type = 2 and ss_from <= :currDate and (ss_to >= :currDate or ss_to is null)"

Sample Resultset of query (currDate='2004-09-01'):
+--------+-------------------------+---------+------------+------------+-----------+
| loc_id | loc_companyname         | ss_type | ss_from    | ss_to      | ss_status |
+--------+-------------------------+---------+------------+------------+-----------+
|      1 | LOCATION 01             |    NULL | NULL       | NULL       |      NULL |
|      2 | LOCATION 02             |       2 | 2004-01-01 | NULL       |         1 |
|      3 | LOCATION 03             |       2 | 2003-01-01 | NULL       |         0 |
+--------+-------------------------+---------+------------+------------+-----------+


When I write the following query in HQL:
Code:
select loc from LocationData as loc
left join fetch loc.statusList as sl

I was expecting Hibernate to discover both "ss_site_id" and "ss_type" (discriminator) and put these into the on-part of the left-join.
Instead the following query is produced:
Code:
select * from tbl_locations left join tbl_site_status on ss_site_id = loc_id

If I put the "ss_type" constaints into the where-part of the query, to many records will be filtered away.
As an example, record number 1 will be removed from the sample resultset.

Is there any way to instruct Hibernate to put extra constraints into the on-part of a left join (without the use of native sql)?

Thanks in advance for any comments.


Kind regards,

Bjarte Andre Eide
Unique Promotions AS
Bergen, Norway

Hibernate version: 2.1.6

Mapping documents:
Code:
   <class name="com.up.camis.data.LocationData" table="tbl_locations">
      <id name="id" column="loc_id">
         <generator class="native"></generator>
      </id>
      <property name="name" column="loc_companyname"></property>

      <set name="statusList">
         <key column="ss_site_id"></key>
         <one-to-many class="com.up.camis.data.LocationStatus"></one-to-many>
      </set>
   </class>

   <class name="com.up.camis.data.StatusData" table="tbl_site_status">
      <composite-id class="com.up.camis.data.StatusDataPK" name="primaryKey">
         <key-property name="type"   column="ss_type"></key-property>
         <key-property name="id"     column="ss_site_id"></key-property>
         <key-property name="from"   column="ss_from"></key-property>
      </composite-id>

      <discriminator column="ss_type" type="string" not-null="true" insert="false"></discriminator>

      <property name="to" column="ss_to"></property>
      <property name="status" column="ss_status"></property>

      <subclass name="com.up.camis.data.LocationStatus" discriminator-value="2">
         <many-to-one name="location" column="ss_site_id" class="com.up.camis.data.LocationData" insert="false" update="false"></many-to-one>
      </subclass>
   </class>


Name and version of the database you are using:MySQL 4.0.20


Top
 Profile  
 
 Post subject:
PostPosted: Sat Sep 04, 2004 10:57 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
No, Hibernate doesn't do this. You need to put a "where" attribute on your collection mapping. Unfortunately, in Hibernate2, the where restriction ends up in the where clause, which hammers your outer join. This is a problem that was fixed in Hibernate3 (it required some refactoring).

After many requests for the discriminator value to filter associations to subclasses, I made a further change to Hibernate3, so that discriminators mapped with force="true" *do* end up in the ON clause. I've never been especially comfortable with this, but too many people disagreed with me, so we give you the option now.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 05, 2004 7:24 pm 
Newbie

Joined: Thu Sep 02, 2004 4:19 am
Posts: 4
Location: Bergen - Norway
I have now installed hibernate3 and are about to test the force="true", but unfortunately I got a problem with the mapping file. The following MappingException is thrown:
Code:
org.hibernate.MappingException: Repeated column in mapping for class com.up.camis.data.StatusData should be mapped with insert="false" update="false": ss_type
        at org.hibernate.persister.AbstractEntityPersister.checkColumnDuplication(AbstractEntityPersister.java:944)
        at org.hibernate.persister.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:278)
        at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:44)
        at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:169)
        at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:914)
        at com.up.test.hibernate.Hibernate3Utility.<clinit>(Hibernate3Utility.java:19)


The only place where I refer to "ss_type" without turning off the update flag (except for in the composite-id tag), is in the <discriminator> tag. This is because this attribute is not accepted by the hibernate-dtd. Does this means that the dtd should be extended to also accept the update attribute, or do I need to register insert/update somewhere else in the mapping file?

The same mapping file is working fine in hibernate2. I have also tried to remove the "force" attribute, which is the only difference between the hibernate2/3 mapping file, but the exception still occurs.

Kind regards,
Bjarte.

Code:
   <class name="com.up.camis.data.StatusData" table="tbl_site_status">
      <composite-id class="com.up.camis.data.StatusDataPK" name="primaryKey">
         <key-property name="type"   column="ss_type"></key-property>
         <key-property name="id"     column="ss_site_id"></key-property>
         <key-property name="from"   column="ss_from"></key-property>
      </composite-id>

      <discriminator column="ss_type" not-null="true" insert="false" force="true"></discriminator>

      <property name="to" column="ss_to"></property>
      <property name="status" column="ss_status"></property>

      <subclass name="com.up.camis.data.SiteStatus" discriminator-value="2">
         <many-to-one name="location" column="ss_site_id" class="com.up.camis.data.LocationData" insert="false" update="false"></many-to-one>
      </subclass>

      <subclass name="com.up.camis.data.ScreenStatus" discriminator-value="1">
         <many-to-one name="auditorium" column="ss_site_id" class="com.up.camis.data.AuditoriumData" insert="false" update="false"></many-to-one>
      </subclass>
   </class>



Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 05, 2004 7:30 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
ack, I'll fix this.

workaround: use <discriminator formula="...""/>


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 05, 2004 7:37 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Are you sure? The code looks good to me...


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 05, 2004 7:38 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Oh. Heh:

Code:
   public boolean isDiscriminatorInsertable() {
      return discriminatorInsertable = true;
   }


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 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.