Циклические отношения в Hibernate - PullRequest
1 голос
/ 21 июля 2011

Я хочу отобразить дерево в спящем режиме, но его сохранение приводит к исключению из-за циклической ссылки (отношения не являются двунаправленными).

class Node {
    @ManyToOne
    Node parent;

    @OneToOne
    Node leftChild;

    @OneToOne
    Node rightChild;
}

Узел N ссылается на своего левого потомка L, который вснова включите ссылки N в качестве его родителя.Кроме того, узел N ссылается на своего правого потомка R, который, в свою очередь, снова ссылается на N как на родителя.Однако я не могу сделать отношения двунаправленными, потому что parent будет обратным как к leftChild, так и rightChild.Каков наилучший способ сделать эту модель устойчивой?

С уважением, Йохен

Ответы [ 2 ]

1 голос
/ 22 июля 2011

Я не вижу проблемы:

@Entity
class Node {
    @Id @GeneratedValue
    private int id;
    private String name;

    @ManyToOne(cascade = CascadeType.ALL)
    Node parent;

    @OneToOne(cascade = CascadeType.ALL)
    Node leftChild;

    @OneToOne(cascade = CascadeType.ALL)
    Node rightChild;

    Node() {}

    public Node(String name) {
        this.name = name;
    }
    // omitted getters and setters for brevity
}

public static void main(String[] args) {
    SessionFactory sessionFactory = new Configuration()
                  .addAnnotatedClass(Node.class)
                  .setProperty("hibernate.connection.url",
                      "jdbc:h2:mem:foo;DB_CLOSE_DELAY=-1")
                  .setProperty("hibernate.hbm2ddl.auto", "create")
                  .buildSessionFactory();
    Session session = sessionFactory.openSession();
    Transaction transaction = session.beginTransaction();
    Node a = new Node("A");
    Node b = new Node("B");
    Node c = new Node("C");
    Node d = new Node("D");
    Node e = new Node("E");
    a.setLeftChild(b);
    b.setParent(a);
    a.setRightChild(c);
    c.setParent(a);
    b.setLeftChild(d);
    d.setParent(b);
    b.setRightChild(e);
    e.setParent(b);
    System.out.println("Before saving:");
    print(a, 1);
    Serializable rootNodeId = session.save(a);
    transaction.commit();
    session.close();

    session = sessionFactory.openSession();
    Node root = (Node) session.load(Node.class, rootNodeId);
    System.out.println("Freshly loaded:");
    print(root, 1);
    session.close();
}

private static void print(Node node, int depth) {
    if (node == null) { return; }
    System.out.format("%" + depth + "s\n", node);
    print(node.getLeftChild(), depth + 1);
    print(node.getRightChild(), depth + 1);
}
0 голосов
/ 22 июля 2011

Hibernate не может различить левого и правого ребенка в вашем примере. Независимо от Hibernate, учитывая две строки в базе данных, которые имеют ссылку на родителя, как вы различаете левый и правый? Итак, если у вас есть несколько записей в одной и той же таблице, которые ссылаются на родительский, у вас фактически есть OneToMany от родительских до дочерних узлов. Поэтому я рекомендую вам смоделировать его как @OneToMany. Затем, если необходимо, предоставьте несколько переходных методов получения, которые будут отличать левого ребенка от правого ребенка в списке детей с помощью некоторой дополнительной логики.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...