1

我有一个基本的树结构,由一个简单的Node类组成,双向链接到它的单亲(根节点可以为空)和一个有序的子列表:

public class Node {
    private Integer xid;
    private Node parent;
    private List<Node> children;
    // getters and setters...
}

我使用休眠将其映射到以下简单的数据库表:

 > select * from node;
 xid | parent | xorder 
-----+--------+--------
   1 |   NULL |      0
   2 |      1 |      0
   3 |      1 |      1
   4 |      1 |      2
(4 rows)

使用以下.hbm休眠映射文件:

<class name="Node" table="node">
    <id name="xid" type="int">
        <generator class="native" />
    </id>
    <many-to-one name="parent" />
    <list name="children" table="node">
        <key column="parent" />
        <list-index column="xorder" />
        <one-to-many class="Node" />
    </list>
</class>

但是,当我尝试使用以下代码在一个父级中打乱元素顺序时:

@Transactional
public void testNode() {
    Node parent = (Node) getSession().get(Node.class, 1);
    Node child0 = parent.getChildren().remove(0);
    parent.getChildren().add(1, child0); // Swap first and second child
    getSession().update(parent);
}

当休眠刷新事务时出现异常:(org.hibernate.exception.ConstraintViolationException ... set parent=null, xorder=null where parent='1' and xid='2'):基本上更新尝试设置xordernull,这显然是数据库模式禁止的。

我在 hbm 映射上尝试了许多组合,但没有成功。当我设置<list>为休眠时inverse="true"不做任何更新,设置元素也无济于事。insert="false" update="false"<many-to-one>

我可能在这里错过了一些东西,无论是在hbm映射中还是在我的代码中,我的感觉是它应该很明显......知道吗?

4

1 回答 1

0

[更新]

以前的答案不正确。我认为违反约束是因为 parent 被设置为 null 并且排序会避免这种情况。由于问题出在 xorder 字段上,我认为在更新之前,您需要手动浏览列表并确保对于列表中的每个项目,每个节点的 xorder 字段与该项目在列表。

例如,当您拉取测试列表时,您可能有 3 个节点。对于列表 xorder=0 中的项目 0,项目 1 的 xorder=1,项目 2 的 xorder=2。如果您对列表中的这些节点重新排序(例如交换 0 和 1,则应确保将新项目 0 的 xorder 值从 1 更改为 0,并且现在是项目 1 的节点的 xorder 应为 1。

要么创建一个新的新子列表,其中节点按正确的顺序排列,然后将 children 属性设置为新列表。

[以前的]

做类似的事情怎么样

Collections.sort(parent.getChildren(), new MyComparator());

现在您所要做的就是编写一个 Comparator 实现来进行您想要的排序更改。我认为这将避免在删除时 parent 设置为 null 的约束冲突。

于 2012-10-14T21:01:10.493 回答