我有一个基本的树结构,由一个简单的Node
类组成,双向链接到它的单个父(对于根节点可以为null)和一个有序的子列表:
public class Node {
private Integer xid;
private Node parent;
private List<Node> children;
// getters and setters...
}
我使用hibernate将其映射到以下简单数据库表:
> select * from node;
xid | parent | xorder
-----+--------+--------
1 | NULL | 0
2 | 1 | 0
3 | 1 | 1
4 | 1 | 2
(4 rows)
使用以下.hbm
hibernate映射文件:
<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);
}
当hibernate刷新事务时我得到一个异常:(org.hibernate.exception.ConstraintViolationException ... set parent=null, xorder=null where parent='1' and xid='2'
):基本上更新尝试将xorder
设置为null
,这显然是数据库模式禁止的。
我在hbm映射上尝试了很多组合,没有成功。当我将<list>
设置为inverse="true"
hibernate不进行任何更新时,在insert="false" update="false"
元素上设置<many-to-one>
也无济于事。
我可能会错过这里的一些内容,无论是在hbm
映射还是在我的代码中,我的感觉是它应该非常明显......任何想法?
答案 0 :(得分:0)
[更新]
之前的回答不正确。我认为约束违规是因为父设置为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实现,以实现您想要的排序更改。我认为这样可以避免在删除时父级被设置为null的约束违规。