tags:

views:

42

answers:

2

There are three object entities: GrandParent, Parent and Child

  • GrandParent contains grandParentId
  • Parent contains object GrandParent, parentId, some attributes, and a list of Child.
  • Child contains childId and some attributes.

There are four tables: GrandParent, Parent, Child, ParentsChildrenList

  • GrandParent whose primary key is {grandParentId}
  • Parent whose primary key is {grandParentId,parentId}
  • Child whose primary key is {grandParentId,childId}
  • ParentsChildrenList whose primary key is {grandParentId,parentId,childId}

Parent and Child are both identified by composite keys.

How should this relationship be mapped? Note that object Child doesn't contain a reference to Parent nor GrandParant, however table Child uses grandParentId as part of its primary key.

This tables structure satisfies the use cases. However, the mapping isn't straight-forward. Any design insight is appreciated.

[--- Update 1 ---]

I added object GrandParent to Child, and created composite key ChildId for mapping to the tables.
The question remains: Can Child borrow a piece of its id from Parent? That way I don't need to introduce GrandParent in Child purely for persistence.

[--- Update 2 ---]

I removed object GrandParent from Child, but kept the ChildId and the method that allows grandParentId to be set. Things still work as expected. I suspect this can't be reduced further.

+1  A: 

The most immediate insight I have is do what hibernate recommends, use surrogate keys. This means every class has a single id for persistence purposes only. You can still map the natural keys. Otherwise you are really fighting the framework, and you are not going to be happy.

That said, a team I was on solved this problem by creating a custom type for the id, where one of the parts was assigned and was was generated.

This might also be helpful http://opensource.atlassian.com/projects/hibernate/browse/HHH-2060

hvgotcodes
Surrogate keys indeed make things a lot easier.
Candy Chiu
@candy, yes they do. You don't want to fight the framework. Not saying this to be condescending, but if you have to ask how to do it, in this case, you probably aren't going to be able to get a good solution. Prove me wrong or use Sks ! ;)
hvgotcodes
A: 

To add to what the other post alluded to, creating a custom type allows for much greater flexibility when defining keys. You could also use a custom id type with a single column but add your own custom logic to generate a surrogate key based upon the parameters to the constructor.

Composite Example:

      (Child ) 
      public class Child implements java.io.Serializable {
         private ChildId id;
             ....
      (ChildId )
      public class ChildId implements java.io.Serializable {
        private long id;
        private long parent_id;
            .....
     (Child.cfg.xml)
          ....
      <composite-id name="id" class="ChildId">
        <key-property name="id" type="long">
            <column name="id" />
        </key-property>
        <key-property name="parent_id" type="long">
            <column name="parent_id" />
        </key-property>
      </composite-id>
         .....

usage:

   Child c = new Child ();
   ChildId cid = new ChildId(null,1);
   c.setId(cid);
   session.save(c);

Creating a custom type allows for alot of customization that is tightly coupled with ORM vs building a solution into the application layer.

ebt
Table Child is reference grandParentId, not parentId.Additionally, how should ChildId populate parentId with the current set up? Note that Child contains its id and some other vanilla attributes only.
Candy Chiu