-->
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.  [ 2 posts ] 
Author Message
 Post subject: foreign key into the same table
PostPosted: Fri Jul 23, 2004 5:12 pm 
Newbie

Joined: Wed Feb 04, 2004 10:31 pm
Posts: 10
Imagine a class Foo like this:
public class Foo
{
private Long m_FooId;
private Foo m_Next;

public Foo getNext() { return m_Next; }
public void setNext(Foo f) { m_Next = f }

public Long getFooId() { return m_FooId; }
public void setFooId(Longf) { m_FooId= f }
}
not there is no way to map the association backwards

TABLE Foo
number foo_id primary key
number next foreign_key foo:foo_id

<class name="Foo" table="Foo">
<id name="fooId" type="long" unsaved-value="null">
<column name="foo_id" sql-type="int8" not-null="true"/>
<generator class="increment"/>
</id>
<many-to-one name="Next" column="next" class="Foo" not-null="false"/>
</class>

This blows up with a stack overflow error - I am suspicious about the many-to-one but an not sure how to declare the self reference


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 23, 2004 10:36 pm 
Beginner
Beginner

Joined: Wed Jul 21, 2004 12:28 pm
Posts: 27
Location: New York
well if you have mapping like this
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="hibernate.ontoitself.TreeNode"
        table="treenode"
        dynamic-update="false"
        dynamic-insert="false"
    >

        <id
            name="id"
            column="id"
            type="java.lang.Long"
        >
            <generator class="identity">
            </generator>
        </id>

        <many-to-one
            name="next"
            class="hibernate.ontoitself.TreeNode"
            cascade="none"
            outer-join="auto"
            update="true"
            insert="true"
            column="next"
        />

        <set
            name="previous"
            lazy="false"
            inverse="true"
            cascade="all"
            sort="unsorted"
        >
              <key
                  column="next"
              />

              <one-to-many
                  class="hibernate.ontoitself.TreeNode"
             
              />
        </set>

    </class>
   
</hibernate-mapping>


the class is like this
Code:
package hibernate.ontoitself;

import java.util.Set;

public class TreeNode {

    protected Long id;
   
    protected TreeNode next;
    protected Set previous;
   
    public Long getId () {
        return id;
    }
    public void setId (Long id) {
        this.id = id;
    }
    public TreeNode getNext () {
        return next;
    }
    public void setNext (TreeNode next) {
        this.next = next;
    }
    public Set getPrevious () {
        return previous;
    }
    public void setPrevious (Set previous) {
        this.previous = previous;
    }
}


the mysql db-creation-script will be like this:

Code:
drop table if exists treenode;

create table treenode (

   id            bigint not null auto_increment,
   next          bigint,
   primary  key (id)
   
);


and tests will look like this (db has to be empty, otherwise tests are not neccesarily testing anything)
Code:
package hibernate.ontoitself;

import java.util.Iterator;
import java.util.Set;

import hibernate.testing.HibernateSession;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.cfg.Configuration;
import junit.framework.TestCase;

public class TreeNodeTests extends TestCase {

    protected SessionFactory sf;
   
    /*
     * @see TestCase#setUp()
     */
    protected void setUp () throws Exception {
        super.setUp ();
       
        try {
           
            sf = new Configuration()
                      .configure ("/hibernate/ontoitself/hibernate.cfg.xml")
                      .buildSessionFactory ();
           
            HibernateSession.sf = sf;
           
        } catch (Exception e) {
            e.printStackTrace ();
            throw e;
        }
       
    }

    /*
     * @see TestCase#tearDown()
     */
    protected void tearDown () throws Exception {
       
        super.tearDown ();
        try { sf.close (); } catch (Throwable t) {}
       
    }

    public void testReadiness () {}
   
    public void testInserts () {
        Session s = null;
        try {
            s = sf.openSession ();

            TreeNode t2 [] = new TreeNode [20];
            TreeNode t1 [] = new TreeNode [4];
            TreeNode t0 [] = new TreeNode [2];
            TreeNode root = new TreeNode ();
           
            for (int i = 0; i < t0.length; i++ ) {
                t0 [i] = new TreeNode ();
                t0 [i].setNext (root);
            }
           
            for (int i = 0; i < t1.length; i++) {
                t1 [i] = new TreeNode ();
                t1 [i].setNext (t0 [i % 2]);
            }
           
            for (int i = 0; i < t2.length; i++) {
                t2 [i] = new TreeNode ();
                t2 [i].setNext (t1 [i%4]);
            }
           
            s.saveOrUpdate (root);
            for (int i = 0; i < t0.length; i++) { s.saveOrUpdate (t0 [i]); }
            for (int i = 0; i < t1.length; i++) { s.saveOrUpdate (t1 [i]); }
            for (int i = 0; i < t2.length; i++) { s.saveOrUpdate (t2 [i]); }
           
            s.flush ();
        } catch (HibernateException he) {
            he.printStackTrace ();
        } finally {
            try { s.close (); } catch (Throwable t) {}
        }
    }
   
    public void testSelects () {
        Session s = null;
        try {
            s = sf.openSession ();

            TreeNode root = (TreeNode) s.find ("from hibernate.ontoitself.TreeNode t where t.next is null").get (0);
            // level 0
            Set level0 = root.getPrevious ();
            assertEquals ("level 0 size ", 2, level0.size ());
            for (Iterator iter0 = level0.iterator(); iter0.hasNext (); ) {
                TreeNode t0 = (TreeNode) iter0.next ();
                assertEquals ("level 0 next", t0.getNext ().getId (), root.getId ());
               
                // level 1
                Set level1 = t0.getPrevious ();
                for (Iterator iter1 = level1.iterator (); iter1.hasNext (); ) {
                    TreeNode t1 = (TreeNode) iter1.next ();
                    assertEquals ("level 1 next", t1.getNext ().getId (), t0.getId ());
                   
                    // level 2
                    Set level2 = t1.getPrevious ();
                    for (Iterator iter2 = level2.iterator (); iter2.hasNext (); ) {
                        TreeNode t2 = (TreeNode) iter2.next ();
                        assertEquals ("level 2 next", t2.getNext ().getId (), t1.getId ());
                    }
                }
            }
   
        } catch (HibernateException he) {
            he.printStackTrace ();
        } finally {
            try { s.close (); } catch (Throwable t) {}
        }
    }   
   
}


should be simple this way. Tests are something to refactor though.


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