JPA経由でツリー構造を保存したいと思います。このモデルは、 と の 2 つのエンティティ クラスで構成され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}
とE = {{child1, parent}, {child2, parent}}
(したがってchild1 -> parent
と) のように、同じ親を持つ 2 つの子頂点を格納できません。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)
を主キーとして選択します。この主キーを使用すると、上記の単純な例のように、同じ親頂点を持つ 2 つの異なる子頂点を含むツリーを格納することはできません。
(MySQL データベース スキーマ内の) 主キーを手動で修正した後でのみ、(tree_id,child_id)
そのツリーを格納できます。
さまざまなマッピングを試しました。ただし、私は常にいくつかの(その他の)問題に遭遇します。
最後に、私の質問: JPA を介してその単純なツリー構造をどのように保存する必要がありますか? 別のマッピングを選択する必要がありますか? モデルを変更する必要がありますか?