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 的不同对象。

我想使用 JPA 插入数据库的所有数据都来自 XML 文件。我用 SAXParser 解析这个文件。当然,id 为 28 的类型条目很多,因为许多电影具有相同的类型。

如果我使用自动生成的 id,数据将不再正确,因为所有 id 都由 XML 文件正确给出。

我怎么解决这个问题?为什么 JPA 不只是忽略这一事实,即该对象已经存在于数据库中,并且只是在我的 m:n 表中插入电影的 ID 和流派?

4

4 回答 4

4

要么你直接在你的流派实例上调用持久化,要么你在电影上调用持久化并且电影->流派映射具有级联持久化。JPA 要求提供者在分离实体上调用持久性时抛出异常,因为持久性意味着您希望提供者插入它,并且它是分离的,因为它已经存在。所以你会得到一个例外。听起来您的解析器无法判断 Genre 实体是同一个实例,因此创建相同数据的多个实例也是如此。如果无法解决此问题,您可以尝试使用合并。合并将首先检查实体实例是新的还是分离的。如果是新的,它将插入,如果是分离的,它将检索数据并在数据库中更新。

其他选项是确保您没有在分离的 Genre 实例上调用persist。删除关系上的级联持久设置,并确保您在新的流派实例上手动调用持久或合并,而不是依赖级联持久设置。

于 2013-05-09T13:33:00.567 回答
3

您只是不能插入具有相同标识符的两个元素。该 id必须是唯一的,否则,数据库无法识别对象(具有讽刺意味的是),这就是它给您异常的原因。

创建一个名为movieId(或您想命名的任何名称)的新字段,并将id来自 xml 的字段存储在该字段中,但不存储在数据库标识符“ id”中。

于 2013-05-09T11:38:14.350 回答
2

您只是不能插入具有相同标识符(id)的两个对象。它抛出 EntityExistsException,

如果实体已经存在。(如果实体已经存在,则EntityExistsException可能会在调用持久操作时抛出,或者EntityExistsException可能PersistenceException会在刷新或提交时抛出。)

解决方案

您可以为movieId 创建一个新字段,该字段将存储来自XML 的电影ID。但这会造成不必要的数据冗余。对于流派,您应该创建一个新表,您将在其中定义movie_genre 映射。为此,您可以使用一对多映射。

于 2019-10-31T09:08:10.180 回答
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 回答