2

JPA経由でツリー構造を保存したいと思います。このモデルは、 と の 2 つのエンティティ クラスで構成されTreeますVertex。クラスVertexには基本的に頂点の名前だけが含まれ、クラスには各子頂点の親頂点を格納するTreeという名前のマッピング( ) が含まれます。parentschild -> 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 を介してその単純なツリー構造をどのように保存する必要がありますか? 別のマッピングを選択する必要がありますか? モデルを変更する必要がありますか?

4

1 に答える 1

0

JPAはあなたがやろうとしていることをできるとは思いません。

マップを配置する場合、E JPAというエンティティは、マップのKとしてVの特定のプロパティを使用し、KとVの間ではなくEとVの間にOneToMany関係を構築することを想定しています。

最も簡単な解決策は、マップを忘れてList<Vertex>、最上位ノードのみを含むクラスにを配置List<Vertex>し、頂点間の子親関係の頂点クラスにもを配置することです。

現在のような構造が必要な場合は、次のような追加のエンティティを導入する必要があると思います。

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

次に、マップがになり、JPAにマップのキーとして親を使用するように指示するためにMap<Vertex, VertexRelation>使用できます。@MapKey(name="parent")

注:追加のエンティティを使用することは単なるアイデアであり、私はそれを自分で試したことがありません。私はいつも木の最初の提案のようなものを使用してきました。

于 2012-08-19T07:23:09.220 に答える