我有一个类似于树形结构的数据集合,其中我确保集合中的所有节点都没有额外的引用,并且已经按拓扑排序排好序,使得根节点排在集合头部,所有叶子节点靠近集合尾部。
我不维护子节点列表,但每个节点都指向其父节点。
如果批处理大小至少与我可以持久化的对象总数一样大,但数据库中的
我的
我的主要抽象节点类大致如下:
@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的后代,例如 A
、B
、C
等等。
问题:
尝试持久化整个树时,我使用以下代码。 // 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_ID
和ROOT_ID
都设置为null
。我在测试时使用H2。请注意,类A
始终是根节点,所有其他对象都可以出现在A
下面的任何级别。我也尝试过s.merge()
,但也不起作用。我已经按照我的业务键实现了equals()
和hashCode()
。我的
equals()
/ hashCode()
方法有问题吗?还是我尝试持久化的方式有问题?我不知道我的代码哪里出错了。我感觉这是个微不足道的错误,而且我正在忽略基本方面。请问有人能帮助我解决吗?我曾试图阅读讨论使用Hibernate进行分层表示的不同博客,但没有什么帮助。
s.clear()
并没有任何效果,只是延迟了错误。我已经不再从事Java工作了-那是我曾经做过的第一个也是最后一个Java工作。但还是感谢您的努力。 :) - Unmanned Player