我想通过 JPA 存储树结构。该模型由两个实体类组成:Tree
和Vertex
。类Vertex
基本上只包含顶点的名称,类Tree
是一个名为的映射parents
,它存储每个子顶点的父顶点(child -> parent
)。
这种结构使我可以简单快速地访问给定子顶点是否具有父顶点以及实际父顶点(如果有)的信息。
我使用以下注释来指定 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}
and E = {{child1, parent}, {child2, parent}}
(因此,child1 -> parent
and child2 -> 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 如何指定连接表中的主键引起的:
不幸的是,EclipseLink 选择了复合键(tree_id,parent_id)
作为主键。使用这个主键,不可能存储任何包含两个不同子顶点且父顶点相同的树,如上述简单示例中所示。
只有在手动修复主键(在 MySQL 数据库模式中)之后,(tree_id,child_id)
我才能存储该树:
我尝试了许多不同的映射;但是,我总是遇到一些(其他)问题。
最后,我的问题是:我应该或可以如何通过 JPA 存储那个简单的树结构?我必须选择不同的映射吗?我必须改变我的模型吗?