2012-08-17 284 views
2

我想通过JPA存储树结构。该模型由两个实体类组成:TreeVertex。类Vertex基本上只包含顶点'名称,类Tree映射名为parents,它存储每个子顶点(child -> parent)的父顶点。如何通过JPA存储树结构?

此结构使我能够简单快速地访问给定子顶点是否具有父顶点以及实际父级(如果有)的信息。

我用下面的注释,以指定JPA(EclipseLink的在我的情况)应该如何存储的关系:

@MapKeyClass(Vertex.class) 
@MapKeyJoinColumn(name = "child_id", nullable = false) 
@OneToMany(targetEntity = Vertex.class, cascade = CascadeType.ALL) 
@JoinTable(name = "bug_492_tree_parents", inverseJoinColumns = { @JoinColumn(name = "parent_id") }) 
private final Map<Vertex, Vertex> parents = Maps.newHashMap(); 

不幸的是,使用上述映射,我不能存储在具有相同父两个子顶点像V = {parent, child1, child2}E = {{child1, parent}, {child2, parent}}(因此,child1 -> parentchild2 -> parent),因为我得到的完整性约束违规:

Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '3-4' for key 'PRIMARY' 
Error Code: 1062 
Call: INSERT INTO bug_492_tree_parents (parent_id, tree_id, child_id) VALUES (?, ?, ?) 

这是通过JPA/EclipseLink的如何specifie引起S IN连接表中的主键:

Incorrect primary key definition

不幸的是,的EclipseLink的动产复合键(tree_id,parent_id)作为主键。使用这个主键,不可能像上面的简单例子那样存储包含两个具有相同父顶点的不同顶点的树。

只有在主键(在MySQL数据库架构)手动固定(tree_id,child_id)我能够存储树:

Fixed primary key

我尝试了许多不同的映射;但是,我总是遇到一些(其他)问题。

最后,我的问题:我该如何或可以通过JPA存储简单的树结构?我必须选择不同的映射吗?我必须改变我的模型吗?

回答

0

我不认为JPA可以做你想做的事情。

中说称为E JPA的实体希望把地图时要使用V的某些属性作为K为地图,并建立不K和V.

E之间和V之间的关系一对多最简单的解决方案是忘记您的地图,并在您的班级中放置List<Vertex>,其中只包含顶级节点也会在您的顶点类中为顶点之间的父级父子关系放置一个List<Vertex>

如果你想要更多像你现在有一个结构,我认为你将不得不引入额外的实体,如:

@Entity 
VertexRelation { 
    private Vertex parent; 
    private Vertex child; 
    ... 
} 

那么你的地图可能会成为一个Map<Vertex, VertexRelation>,你可以使用@MapKey(name="parent")告诉JPA你想使用父母作为地图的关键。

注:使用额外的实体只是一个想法,我从来没有尝试过自己。我一直使用类似于我对树木的第一个建议。