Hibernate:持久化树形结构

4
我有一个类似于树形结构的数据集合,其中我确保集合中的所有节点都没有额外的引用,并且已经按拓扑排序排好序,使得根节点排在集合头部,所有叶子节点靠近集合尾部。

我的主要抽象节点类大致如下:

@Entity
public abstract class Node {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public long ID;

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name = "parent_id", insertable = false, updatable = false)
    Node parent;

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name = "root_id", insertable = false, updatable = false)
    Node root;
}

我不维护子节点列表,但每个节点都指向其父节点。 root 引用是一个方便的字段,用来引用树的根节点。例如,对于删除整棵树,这将更容易。现在,我有许多来自Node的后代,例如 ABC 等等。 问题: 尝试持久化整个树时,我使用以下代码。
    // Check for extraneous references, and sort them topologically.
    Session s = hibernate.openSession();
    Transaction tx = s.beginTransaction();
    try {
        int i = 0;
        for (Node p: objects) {
            if (p.parent == null) {
                throw new IOException("Parent is `null`.");
            }
            s.persist(p);
            if (i % batchSize == 0) {
                s.flush();
                s.clear();
            }
            i++;
        }
        tx.commit();
    }
    catch (Throwable t) {
        log.error(t.getMessage(), t);
        tx.rollback();
        throw new IOException(t);
    }

这种方法无法正确地持久化对象。如果批处理大小太小,我会收到一个 PersistentObjectException 错误信息:

org.hibernate.PersistentObjectException: detached entity passed to persist: com.example.Node

如果批处理大小至少与我可以持久化的对象总数一样大,但数据库中的PARENT_IDROOT_ID都设置为null。我在测试时使用H2。请注意,类A始终是根节点,所有其他对象都可以出现在A下面的任何级别。我也尝试过s.merge(),但也不起作用。我已经按照我的业务键实现了equals()hashCode()
我的equals()/ hashCode()方法有问题吗?还是我尝试持久化的方式有问题?我不知道我的代码哪里出错了。我感觉这是个微不足道的错误,而且我正在忽略基本方面。请问有人能帮助我解决吗?我曾试图阅读讨论使用Hibernate进行分层表示的不同博客,但没有什么帮助。
1个回答

0

尝试移除s.clear()

这基本上是将对象从持久化上下文中分离,这可能导致异常detached entity passed to persist


天啊!我5年前问过这个问题,当时我在Java/Hibernate上做了一个简短的工作,被迫将图形建模为表格。移除s.clear()并没有任何效果,只是延迟了错误。我已经不再从事Java工作了-那是我曾经做过的第一个也是最后一个Java工作。但还是感谢您的努力。 :) - Unmanned Player

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接