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

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'):基本上,更新尝试将xorder设置为null,这显然是数据库架构所禁止的。

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

我可能在这里错过了一些东西,无论是在hbm映射中还是在我的代码中,我的感觉是它应该非常明显……有什么主意吗?

最佳答案

[更新]

先前的答案不正确。我认为违反约束是因为将parent设置为null,而排序可以避免这种情况。由于问题出在xorder字段上,因此我认为在进行更新之前,您需要手动浏览列表,并确保对于列表中的每个项目,每个节点的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实现,以实现所需的排序更改。我认为这可以避免在父元素被移除时设置为null的约束违规。

关于java - hibernate :在双向有序树中混洗子节点,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12886389/

10-10 16:20