我目前面临的问题如下:
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)
因此Exception告诉我,我想插入两个具有相同主键ID的不同对象。
我想要使用JPA插入数据库的所有数据都来自XML文件。我用SAXParser解析这个文件。当然,有很多类型为28的流派条目,因为很多电影都有相同的类型。
如果我使用自动生成的ID,则数据将不再正确,因为XML文件正确地给出了所有id。
我该如何解决这个问题?为什么JPA不只是忽略了这个事实,这个对象已经存在于数据库中,只是在我的m:n表中插入电影和类型的id?
答案 0 :(得分:2)
要么直接调用你的Genre实例上的持久性,要么你正在调用电影,而电影 - >类型映射已经级联持续存在。 JPA要求提供程序在分离的实体上调用persist时抛出异常,因为persist意味着您希望提供程序插入它,并且它已经分离,因为它已经存在。所以你会得到一个例外。听起来你的解析器无法判断Genre实体是同一个实例,因此创建了相同数据的多个实例。如果无法解决此问题,您可以尝试使用合并。合并将首先检查实体实例是新实例还是分离实例。如果它是新的,它将插入,而如果它是分离的,它将检索数据并在数据库中更新它。
其他选项是确保您不在分离的Genre实例上调用persist。删除关系上的级联持久设置,并确保您手动调用持久化或合并新的Genre实例,而不是依赖级联持久设置。
答案 1 :(得分:1)
您无法插入具有相同标识符的两个元素。 id 必须唯一,如果没有,数据库无法识别对象(讽刺的是),这就是为什么它会给你例外。
创建一个名为movieId
的新字段(或任何您想要命名的字段),并将xml中的id
存储在该字段中,但不存储在数据库标识符“id
”中
答案 2 :(得分:1)
您不能插入具有相同标识符(id)的两个对象。 它抛出EntityExistsException,
如果实体已经存在。 (如果实体已经存在,则在调用persist操作时可能会抛出
EntityExistsException
,或者可能在刷新或提交时抛出EntityExistsException
或另一个PersistenceException
。)
解决方案
您可以为movieId创建一个新字段,该字段将存储XML中电影的ID。但这会造成不必要的数据冗余。对于流派,您应该创建一个新表,在其中定义movie_genre映射。为此,您可以使用一对多映射。
答案 3 :(得分: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;
}