2

私が現在直面している問題は次のとおりです。

Exception in thread "main" javax.persistence.EntityExistsException: a different object with the same identifier value was already associated with the session: [de.entities.Genre#28]
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1359)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1316)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:881)
at de.model.DatabaseBuilder.importData(DatabaseBuilder.java:87)
at de.main.Main.main(Main.java:55)

したがって、例外は、同じ主キー ID を持つ 2 つの異なるオブジェクトを挿入する必要があることを示しています。

JPA を使用してデータベースに挿入したいすべてのデータは、XML ファイルから取得されています。このファイルを SAXParser で解析します。もちろん、同じジャンルの映画はたくさんあるので、id 28 のジャンル エントリはたくさんあります。

自動生成された ID を使用すると、すべての ID が XML ファイルによって正しく指定されるため、データは正しくなくなります。

どうすればこの問題を解決できますか? JPA は、このオブジェクトがデータベースに既に存在し、映画の ID とジャンルを m:n テーブルに挿入するという事実を無視しないのはなぜですか?

4

4 に答える 4

4

Genre インスタンスで persist を直接呼び出しているか、movie で persist を呼び出しており、movie->Genre マッピングにカスケード持続があります。JPA では、デタッチされたエンティティで persist が呼び出されたときにプロバイダーが例外をスローする必要があります。これは、persist はプロバイダーにエンティティを挿入することを意味し、既に存在するためデタッチされているためです。したがって、例外が発生します。パーサーは Genre エンティティが同じインスタンスであることを認識できないため、同じデータの複数のインスタンスを作成しているようです。これを修正できない場合は、代わりにマージを使用してみてください。Merge は最初に、エンティティ インスタンスが新規であるか分離されているかをチェックします。新しい場合は挿入し、分離されている場合はデータを取得してデータベースで更新します。

他のオプションは、切り離された Genre インスタンスで永続化を呼び出していないことを確認することです。リレーションシップのカスケード永続化設定を削除し、カスケード永続化設定に依存するのではなく、新しいジャンル インスタンスで永続化またはマージを手動で呼び出すようにします。

于 2013-05-09T13:33:00.567 に答える
3

同じ識別子を持つ 2 つの要素を挿入することはできません。そのIDは一意でなければなりません。そうでない場合、データベースはオブジェクトを識別できません(皮肉なことに)。そのため、例外が発生します。

という名前の新しいフィールドmovieId(または任意の名前) を作成idし、そのフィールドに xml から を格納しますが、データベース識別子 " id" には格納しません。

于 2013-05-09T11:38:14.350 に答える
0

あなたのジャンルのマッピングは間違った関係にあるようです。あなたのユースケースから、それは多対多の関係であるべきだと思います。

ジャンルの有効なマッピングは次のようになります。

@ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.MERGE, CascadeType.REFRESH, })
@JoinTable(name = "MovieGenre", joinColumns = { @JoinColumn(name = "Movie_Id") }, inverseJoinColumns = { @JoinColumn(name = "Genre_Id") })
public Set<Genre> getGenres() {
     return this.genres;
}
于 2013-05-09T12:41:24.797 に答える