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: Object property (anonymous foreign reference)...
PostPosted: Thu Dec 08, 2005 6:55 pm 
Beginner
Beginner

Joined: Thu Dec 08, 2005 6:49 pm
Posts: 49
My appologies if this has been discussed before.

I have a table that is able to reference any other table. It does this by storing the table name and primary key of the foreign record in a pair of string fields.
What is the cleanest way to handle this?
I'm basically trying to avoid having to write the lookup code myself but still be able to use my objects as follows:

Code:
if (obj.Parent is Car)
    //do something
else if (obj.Parent is Horse)
    //do something else


Note that my "Car" and "Horse" objects in the above example do not inherit from anything common.
I'm also trying to keep my objects free from NHibernate references.

Cheers


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 09, 2005 1:33 am 
Regular
Regular

Joined: Thu Oct 27, 2005 8:06 am
Posts: 55
Location: München, Germany
There is no need for Car and Horse to inherit from something common. The clean way to achieve what you suggest is to subclass that child class that your code snippet appears to come from. If you can achieve this, i.e. have a CarChild class containing a reference to a Car, and a HorseChild class, etc., then you can use your table_name column as discriminator for this inheritance structure, and you are on safe ground. A major benefit of this will be that your get rid of those runtime tests on clsses, which are inherently unclean.

If you can't go this way, then your object references have to be of type Object, don't they? As far as I understand the Hibernate mapping system, your mappings have to match your class structures, so you would have to map that relationship to Object, which won't be of much use to you.

You could look whether there is something for you in section 3.3.4 of Hibernate in Action: "Manipulating metadata at runtime". First find out dynamically what kind of object you are referencing, then try to make Hibernate believe this. However, I doubt that you will gain productivity over generating the SQL accessor yourself.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 09, 2005 2:38 am 
Beginner
Beginner

Joined: Thu Dec 08, 2005 6:49 pm
Posts: 49
Cheers for the interesting info. This leads me to my next question.

Is it possible to create a many-to-one relationship that doesn't create a database level foreign key constraint? This is necessary if your solution is to work because both CarChild and HorseChild both have a many-to-one based on the same ParentID field.

Obviously storing both CarIDs and HorseIDs in the same place wont work with a constraint.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 09, 2005 4:16 am 
Regular
Regular

Joined: Thu Oct 27, 2005 8:06 am
Posts: 55
Location: München, Germany
Just try this mapping strategy on a few classes and look what hbm2ddl generates for you. I don't know which constraints will be generated, and whether hbm2ddl offers you any options for constraint generation. But that's no crucial question, as no one forces you to generate your database from Hibernate mapping files. If it doesn't work as you need it, you could still run the generation to get the bulk of names and data types right, and manually tweak the database design to meet your needs. You may, of course, not change any names or data types mentioned in your mapping files, but removing a constraint should be no problem.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 09, 2005 4:33 am 
Regular
Regular

Joined: Thu Oct 27, 2005 8:06 am
Posts: 55
Location: München, Germany
Afterthought: You'll have to check anyway whether the solution I suggested works. I quickly browsed the Hibernate documentation and didn't find an explicit hint about this.

The core of my suggestion is to map inheritance by the table-per-class-hierarchy method of Hibernate. This allows you to use your table name column as subclass discriminator.

However, all published examples of table-per-class-hierarchy that I'm aware of are built in a way that if two subclasses S1 and S2 have attributes as1 and as2, then those two attributes are mapped to different database columns. What you want, however, is to map them to the same column. They have a different Java type (Car or Horse), but the same database type (maybe Long). So the database should support this, but I don't know whether Hibernate does. I'm neither aware of a rule saying as1 and as2 have to be mapped to separate columns, nor of a rule saying they may be mapped to the same.

But that's easy to test. Tell us the result after you tried.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 09, 2005 11:16 am 
Beginner
Beginner

Joined: Thu Dec 08, 2005 6:49 pm
Posts: 49
Everything seems to work just nicely once I remove the foreign key constraint from the database. I can insert different IDs into the same column based on the subclass used and select them out (in a new session) with no problems.

It's a shame there isn't an attribute in the many-to-one relationship that instructs SchemeExport to skip foreign key constraint creation. I am writing an application in which the user is able to create as many databases as they want (MSAccess or SQLite files) and I'd rather not have to write special code to remove constraints (especially since they seem to named randomly).

Getting back to my original requirement of having an object property rather than subclasses with typed properties, I also tried specifying subclasses as the same type as the parent. Now obviously the discriminator field couldn't be automatically filled during an insert as the subclass type would usually indicate the discriminator value to be stored. So I tried setting up a property for the discriminator and manually filling it, but unfortunately this approach didn't work.

Anyway, thanks for the help. I'll be creating a subclass for all the different tables that I may need to reference.

Here is my test hbm:

Code:
<class name="Event">
  <id name="ID">
    <generator class="uid" />
  </id>
  <discriminator column="ParentType" />
  <subclass name="CarEvent" discriminator-value="Car">
    <many-to-one name="Parent" column="ParentID" />
  </subclass>
  <subclass name="HorseEvent" discriminator-value="Horse">
    <many-to-one name="Parent" column="ParentID" />
  </subclass>
</class>

<class name="Car">
  <id name="ID">
    <generator class="uid" />
  </id>
  <property name="Name" />
</class>

<class name="Horse">
  <id name="ID">
    <generator class="uid" />
  </id>
  <property name="Name" />
</class>


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.