-->
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.  [ 8 posts ] 
Author Message
 Post subject: Advanced Parent/Child Question
PostPosted: Mon Sep 27, 2004 3:55 pm 
Newbie

Joined: Mon Sep 27, 2004 3:38 pm
Posts: 18
Location: Angleton, TX
I have 3 POJOs. They are Contact, Document, and History. I'm trying to set up a parent/child relationship using Contact/History AND Document/History. I want my Contact table and Document table to both share the same History table in the database. Any help on how to create a mapping document for this would be appreciated. Thanks!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 28, 2004 12:43 pm 
Newbie

Joined: Mon Sep 27, 2004 3:38 pm
Posts: 18
Location: Angleton, TX
I apologize for not supplying a lot of detail with the last post. I'm new to Hibernate and am looking for some suggestions from experienced users on how best to implement my design. Consider the fillowing 3 tables:

Code:
create table Contact (
    UID char(32) not null,
        . . .
        . . .
   );

create table Document (
    UID char(32) not null,
        . . .
        . . .
    );

create table History (
    UID char(32) not null,
    PARENT_UID char(32) not null,
        . . .
        . . .
    );


I need to be able to track the history of changes that happen to both the Contact and Document objects. I'd like them to both share the same history table. This seems like a simple thing to do, but Hibernate doesn't appear to allow this type of one-to-many relationship directly. I'm just wondering what the best approach would be to solving this problem.

Once again, thanks for any and all help.

Jeff Barriault


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 28, 2004 6:31 pm 
Regular
Regular

Joined: Sat Aug 28, 2004 4:15 pm
Posts: 61
Jeff,

I dont think this is exactly an 'advanced' parent child issue. However, I recommend you read the section of the reference guide that talks about parent child relationships. Also, you'll be able to find here in the forums several examples of parent child relationships. Hibernate certainly does provide "direct" support for one-to-many, many-to-one, many-to-many, etc.. relationships.

I apologize for a RTFM response but that is basically the story here.

Joe

_________________
Joe W


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 28, 2004 8:51 pm 
Newbie

Joined: Mon Sep 27, 2004 3:38 pm
Posts: 18
Location: Angleton, TX
Joe,

I hope you don't mind me disagreeing with you, a little bit anyway. I've read the great manuals, and they have been a lot of help. Let me try providing an example of what I am trying to accomplish.

Mapping.hbm.xml
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>

  <class name="eg.ParentOne" table="PARENT_ONE">
   
    <id name="id" type="int" column="UID">
      <meta attribute="scope-set">protected</meta>
      <generator class="uuid.hex"/>
    </id>

    <set name="children" table="CHILD" inverse="true">
      <key column="PARENT_UID"/>
      <one-to-many class="eg.child"/>
    </set>

  </class>

  <class name="eg.ParentTwo" table="PARENT_TWO">
   
    <id name="id" type="int" column="UID">
      <meta attribute="scope-set">protected</meta>
      <generator class="uuid.hex"/>
    </id>

    <set name="children" table="CHILD" inverse="true">
      <key column="PARENT_UID"/>
      <one-to-many class="eg.child"/>
    </set>

  </class>
 
    <class name="eg.Child" table="CHILD">
   
    <id name="id" type="int" column="UID">
      <meta attribute="scope-set">protected</meta>
      <generator class="uuid.hex"/>
    </id>

    <many-to-one name="parent" column="PARENT_UID" not-null="true"/>

  </class>
 

</hibernate-mapping>


hbm2java output:
Code:
Buildfile: F:\eclipse3\workspace\Hibernate\build.xml
prepare:
codegen:
[hbm2java] Processing 1 files.
[hbm2java] Building hibernate objects
[hbm2java] 19:38:08,294  WARN ClassMapping:264 - many-to-one "parent" in class Child is missing a class attribute
BUILD SUCCESSFUL
Total time: 6 seconds


The problem I'm having is the many-to-one relationship in the child. I want the PARENT_UID column to refer to either ParentOne or ParentTwo. This is the part that isn't clear in the manual, or maybe I missed it.

I've searched through the forums and the wikki and haven't found anything even remotely similar to this. I don't mind reading how to do things myself so if you'd like to point me in the right direction I'd appreciate.

Thanks again,

Jeff Barriault


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 28, 2004 9:51 pm 
Regular
Regular

Joined: Sat Aug 28, 2004 4:15 pm
Posts: 61
Jeff,

I dont see any obvious issues with your mapping file.

Although, there is one issue to consider. You've got the error

Quote:
[hbm2java] 19:38:08,294 WARN ClassMapping:264 - many-to-one "parent" in class Child is missing a class attribute


that is coming from your ddl generator. I imagine this is because as the reference manual states

Quote:
5.1.10. many-to-one

An ordinary association to another persistent class is declared using a many-to-one element. The relational model is a many-to-one association. (Its really just an object reference.)

<many-to-one
name="propertyName" (1)
column="column_name" (2)
class="ClassName" (3)
cascade="all|none|save-update|delete" (4)
outer-join="true|false|auto" (5)
update="true|false" (6)
insert="true|false" (6)
property-ref="propertyNameFromAssociatedClass" (7)
access="field|property|ClassName" (8)
unique="true|false" (9)
/>
...
class (optional - defaults to the property type determined by reflection): The name of the associated class.


From that, you can see that reflection is used to determine the class type of the parent class [If you dont specify the class type]. So, in your case you would have two types. Obviously this wont work. So, what you'll need to do is consider having the two parent classes extend a base class that is "HistoryDataAble" or something. Then, you specify this class as the class of the parent object in the many-to-one mapping. You get the idea?

Im sure you've read all about subclasses and how those map to tables.

I am assuming that you want the historical data from each parent to go to the same table that the parents are fairly similar.

Hopefully that clears this up a bit.

_________________
Joe W


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 28, 2004 10:16 pm 
Newbie

Joined: Mon Sep 27, 2004 3:38 pm
Posts: 18
Location: Angleton, TX
Thanks Joe,

Now we're getting somewhere. So we've moved from a "simple" one-to-many mapping onto a little more "advanced" mapping involving sub-classes. That sounds like a good way to implement what I'm trying to accomplish. I did a bunch more reading and discovered the 'any' type and tried this for a mapping file:

Mapping.hmb.xml
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>

  <class name="eg.ParentOne" table="PARENT_ONE">
   
    <id name="id" type="string">
      <meta attribute="scope-set">protected</meta>
     <column name="UID" sql-type="CHAR(32)"/>
      <generator class="uuid.hex"/>
    </id>

    <set name="children" table="CHILD" inverse="true">
      <key column="PARENT_UID"/>
      <one-to-many class="eg.Child"/>
    </set>

  </class>

  <class name="eg.ParentTwo" table="PARENT_TWO">
   
    <id name="id" type="string">
      <meta attribute="scope-set">protected</meta>
     <column name="UID" sql-type="CHAR(32)"/>
      <generator class="uuid.hex"/>
    </id>

    <set name="children" table="CHILD" inverse="true">
      <key column="PARENT_UID"/>
      <one-to-many class="eg.Child"/>
    </set>

  </class>
 
    <class name="eg.Child" table="CHILD">
   
    <id name="id" type="string">
      <meta attribute="scope-set">protected</meta>
      <column name="UID" sql-type="CHAR(32)"/>
      <generator class="uuid.hex"/>
    </id>

   <any name="parent" id-type="string">
      <column name="PARENT"/>
      <column name="PARENT_UID" sql-type="CHAR(32)"/>
   </any>

  </class>
 

</hibernate-mapping>


This seems to work too. Although the extra PARENT column doesn't seem to be necessary if I'm using a globally unique UID.

Before I head down the wrong path here, which method is better? Mapping via 'any' or subclasses? I'm also wondering if I can start with a Base class that has just an ID and subclass ParentOne, ParentTwo and Child from Base? Then I could use a "native" id generator. Just a thought here. Please let me know if I'm heading down the right path.

Thanks again,

Jeff Barriault


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 28, 2004 10:50 pm 
Regular
Regular

Joined: Sat Aug 28, 2004 4:15 pm
Posts: 61
Jeff,

If I understand your point, you are trying to have a bidrectional association from two different types of parent to a single child class.

So,

ParentA has one to many Child
ParentB has one to many Child
Child has many to one [ something ... possibly a superclass for parents ]

The whole problem here is the [something] portion. IF you are trying to have a bidirectional association, you cannot simulate that type of relationship using the <any> tag. With the any tag, I think you'll be able to figure out who a Child's daddy is, but not which particular Child a daddy has.

As they stated in the reference manual it's only useful for special cases such as audit logs ..... On the surface, it sounded like you want an audit log. But, I'm getting the impression you're wanting more.


So, I'd recommend you head down the SuperParent base class path. For that, something such as


Code:
Class SuperParent{
     History historyEntry;
}

Class ParentA extends SuperParent{
  ...   
}

Class ParentB extends SuperParent{
  ...   
}



Then you do the mapping for the base class that will allow you to have the bidirectional association since all SuperParents have history data and all classes that extend SuperParent have Child...... ok so Im getting tired but I think you get the idea.



As for your remarks about native id generation.....I dont really follow :)

_________________
Joe W


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 29, 2004 8:45 pm 
Newbie

Joined: Mon Sep 27, 2004 3:38 pm
Posts: 18
Location: Angleton, TX
I was just thinking that if I subclassed a superclass I wouldn't need to use a globally unique UID. I could use:

Code:
<generator class="native"/>


Since all classes would be a subclass of my superclass, they would all have a globally unique ID.

The actual data I'm trying to model is pretty complex. If you're interested in checking it out yourself, you can find it here: http://xml.coverpages.org/pdx.html

Thanks again for your help. At least now I believe I am on the correct path.

JB


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