-->
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.  [ 4 posts ] 
Author Message
 Post subject: Parent/Child with just one table (composite keys, too!)
PostPosted: Fri Oct 21, 2005 9:21 am 
Newbie

Joined: Fri Oct 21, 2005 4:31 am
Posts: 8
Location: Bern / Switzerland
Hi all,

I'm new to Hibernate and have the following problem: Basically, all I'd like to map is a Parent/Child relationship on a legacy app. The table "Tree" looks like

---------------------------------------------------------
| id1 | id2 | name | parent_id1 | parent_id2 |
---------------------------------------------------------

where id1 and id2 is a composite key and parent_id1 and parent_id2 are foreign keys to the same table (a parent has multiple childs).

The goal is to get a Java Object tree with the root element containing all its direct children in a collection "children" (and so forth). Then I'd like to export this tree to a XML document.

So far I have a TreeId class for the composite key, a Tree class with getters and setters for treeId, name and children (collection) and this Tree.hbm.xml:

Code:
...

  <class name="Tree">
 
    <composite-id name="id" class="TreeId">
      <key-property name="id1"/>
      <key-property name="id2"/>
    </composite-id>
   
    <set name="children" table="Tree" inverse="true" cascade="all-delete-orphan">
      <key>
        <column name="parentId1" not-null="true"/>
        <column name="parentId2" not-null="true"/>
      </key>
      <one-to-many class="Tree"/>
    </set>
   
    <property name="name"/>
   
  </class>
...


This produces empty foreign keys on inserts. Is there any chance to make this work? If so, how would performance be?

BTW, if this table was a nested Set, could hibernate efficiently handle that? (just curious)

Thanks for all answers!

Regards,
Simon


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 21, 2005 10:28 am 
Beginner
Beginner

Joined: Tue Nov 25, 2003 3:33 pm
Posts: 35
this is what worked for me:

Code:
package domain;

import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratorType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.hibernate.annotations.Cascade;
import edu.columbia.law.tas.CompositeKey;

@Entity
@Table(name="csample")
@IdClass(value=CompositeKey.class)
public class CompositeIdEntity {
   
    private CompositeKey key = new CompositeKey ();
    private String name;
    private Set<CompositeIdEntity> children;
    private CompositeIdEntity parent;
   
    public CompositeIdEntity () {}
    public CompositeIdEntity (CompositeKey key) {
        this.key = key;
    }

    @OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER,mappedBy="parent")
    @Cascade(value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    public Set<CompositeIdEntity> getChildren () { return children; }
    public void setChildren (Set<CompositeIdEntity> children) { this.children = children; }

    @Id(generate=GeneratorType.NONE)
    @Column(insertable=false,updatable=false)
    public CompositeKey getKey () { return key; }
    public void setKey (CompositeKey key) { this.key = key; }

    public String getName () { return name; }
    public void setName (String name) { this.name = name; }

    @ManyToOne
    @JoinColumns({
        @JoinColumn (name="pid1"),
        @JoinColumn (name="pid2")
    })
    public CompositeIdEntity getParent () { return parent; }
    public void setParent (CompositeIdEntity parent) { this.parent = parent; }
   
    public void addChild (CompositeIdEntity child) {
        if (this.getChildren() == null) {
            this.setChildren(new HashSet<CompositeIdEntity> ());
        }
        child.setParent(this);
        this.getChildren().add(child);
    }
   
    @Transient
    public Long getId1 () { return getKey().getId1(); }
    public void setId1 (Long id1) { key.setId1 (id1); }
   
    @Transient
    public void setId2 (Long id2) { key.setId2 (id2); }
    public Long getId2 () { return key.getId2 (); }
   
   
}


then test will look like this:
Code:
CompositeIdEntity p = new CompositeIdEntity (new CompositeKey(new Long (0), new Long (0)));
p.setName("Parent");

CompositeIdEntity c0 = new CompositeIdEntity (new CompositeKey(new Long (0), new Long (1)));
c0.setName("Child 0");
                       
CompositeIdEntity c1 = new CompositeIdEntity (new CompositeKey(new Long (0), new Long (2)));
c1.setName("Child 1");
                       
p.addChild(c0);
p.addChild(c1);

session.saveOrUpdate(p);


and SQL DDL:
Code:
DROP TABLE IF EXISTS `hibernate-goofing`.`csample`;
CREATE TABLE `csample` (
  `id1` int(10) unsigned NOT NULL default '0',
  `id2` int(10) unsigned NOT NULL default '0',
  `name` varchar(45) default NULL,
  `pid1` int(10) unsigned default '0',
  `pid2` int(10) unsigned default '0',
  PRIMARY KEY  (`id1`,`id2`)
);


worked charmingly well :-)


Top
 Profile  
 
 Post subject: Re: Parent/Child with just one table (composite keys, too!)
PostPosted: Fri Oct 21, 2005 9:22 pm 
Beginner
Beginner

Joined: Tue Oct 18, 2005 3:57 pm
Posts: 48
Location: Los Angeles, CA
saimonsez wrote:
This produces empty foreign keys on inserts. Is there any chance to make this work? If so, how would performance be?

Just allow NULL for parent key columns:
Code:
    <set ... >
      <key>
        <column ... not-null="false"/>
        <column ... not-null="false"/>
      </key>
    </set>

saimonsez wrote:
BTW, if this table was a nested Set, could hibernate efficiently handle that? (just curious)

Don't worry about Hibernate's efficiency because:
1) you can always set lazy="true", and
2) if there's any performance issues, chances are they won't be in Hibernate. :)

jd


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 24, 2005 5:03 am 
Newbie

Joined: Fri Oct 21, 2005 4:31 am
Posts: 8
Location: Bern / Switzerland
Thanks for the replies! Unfortunately, I have to wait until next weekend to test it (loads of work ...).

I've never worked with these ejb tags, but I guess that the Hibernate Ant Tools are needed to generate XML configs?

Regards,
Simon


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