【问题标题】:Cyclic relationships in HibernateHibernate 中的循环关系
【发布时间】:2011-10-10 11:58:36
【问题描述】:

我想在休眠中映射一棵树,但由于循环引用(关系不是双向的),持久化它会导致异常。

class Node {
    @ManyToOne
    Node parent;

    @OneToOne
    Node leftChild;

    @OneToOne
    Node rightChild;
}

节点 N 引用其左子节点 L,而左子节点 L 又再次引用 N 作为其父节点。此外,节点 N 引用其右子节点 R,而右子节点 R 又再次引用 N 作为父节点。但是,我不能使关系成为双向的,因为父级将是 leftChild 和 rightChild 的逆。使该模型具有持久性的最佳方法是什么?

问候, 乔辰

【问题讨论】:

    标签: hibernate relationship


    【解决方案1】:

    我没有发现问题:

    @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);
    }
    

    【讨论】:

    • 适用于 Hibernate 4.3.11。谢谢!
    【解决方案2】:

    在您的示例中,Hibernate 无法区分左右孩子。不管Hibernate,给定数据库中有两行引用了父级,如何区分左右?因此,如果您在同一个表中有多个引用父节点的条目,那么您实际上从父节点到子节点都有OneToMany。因此,我建议您将其建模为@OneToMany。然后,如有必要,提供一些临时 getter,它们将通过一些额外的逻辑来区分孩子列表中的左孩子和右孩子。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      相关资源
      最近更新 更多