Jadiel de Armas
Jadiel de Armas

Reputation: 8792

Persisting circular references in Hibernate

I have the following situation:

@Entity
class Foo {

    @ManyToOne(cascade=CascadeType.PERSIST)
    @JoinColumn(name="parent_id")
    Foo father;

    @OneToOne(cascade=CascadeType.PERSIST)
    @JoinColumn(name="left_child_id")
    Foo left_child;

    @OneToOne(cascade=CascadeType.PERSIST)
    @JoinColumn(name="right_child_id")
    Foo right_child;

}

I want to persist many of them. Before placing them in a list, I set the relationships among them, and place them in the list so that the parents appear always before the children. When I persist I do:

tx=session.beginTransaction();
List<Foo> foos=new LinkedList<Foo>();
//Some code here to establish relationships
enter code here
for (Foo foo : foos){
    session.save(foo);
}
tx.commit();

But by doing this I receive the following error: ERROR: Cannot add or update a child row: a foreign key constraint fails (package.Foo, CONSTRAINT FK_r1pg1dvb3vnuml2e7tw1x2doc FOREIGN KEY (left_child_id) REFERENCES Foo (id`)).

Is it possible for me to persist keeping the circular references? I would like to do it like that if I could. Any ideas on how to persist this are welcome.

Upvotes: 1

Views: 1697

Answers (1)

Learner
Learner

Reputation: 21425

I tried this but I did not get any error, here is my code:

Foo.java

@Entity public class Foo {

@Id
@GeneratedValue
private int id;

@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "parent_id")
Foo father;

@OneToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "left_child_id")
Foo left_child;

@OneToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "right_child_id")
Foo right_child;

// Setters & Getters

}

Program that saves the Foo objects:

    Session session = HibernateUtil.getSessionFactory().openSession();
    session.getTransaction().begin();

    Foo father = new Foo();
    Foo leftChild = new Foo();
    Foo rightChild = new Foo();

    Foo foo = new Foo();
    foo.setFather(father);
    foo.setLeft_child(leftChild);
    foo.setRight_child(rightChild);

    session.persist(foo);
    session.getTransaction().commit();

The data in database:

SQL> select * from foo;

        ID  PARENT_ID LEFT_CHILD_ID RIGHT_CHILD_ID
---------- ---------- ------------- --------------
         2
         3
         4
         1          2             3              4

Now if I try to save multiple Foo objects, they are also saved correctly:

private static void saveElements() {
    Session session = HibernateUtil.getSessionFactory().openSession();
    session.getTransaction().begin();

    Foo foo1 = getFooObject();
    Foo foo2 = getFooObject();

    Foo foo = new Foo();
    Foo father = new Foo();
    Foo leftChild = new Foo();
    Foo rightChild = new Foo();

    foo.setFather(father);
    foo.setLeft_child(leftChild);
    foo.setRight_child(rightChild);

    foo.setFather(foo1.getFather());
    foo.setLeft_child(foo2.getFather());

    session.persist(foo1);
    session.persist(foo2);
    session.persist(foo);
    session.getTransaction().commit();

}

private static Foo getFooObject() {
    Foo foo = new Foo();
    Foo father = new Foo();
    Foo leftChild = new Foo();
    Foo rightChild = new Foo();

    foo.setFather(father);
    foo.setLeft_child(leftChild);
    foo.setRight_child(rightChild);
    return foo;
}



SQL> select * from foo;

        ID  PARENT_ID LEFT_CHILD_ID RIGHT_CHILD_ID
---------- ---------- ------------- --------------
         2
         3
         4
         1          2             3              4
         6
         7
         8
         5          6             7              8
        10
         9          2             6             10

10 rows selected.

Upvotes: 1

Related Questions