在EclipseLink中,我遇到了一个问题,即元素被插入两次,导致主键违规。方案如下: 我有三个实体,元素,限制和限制元素。实体RestrictionElement充当两个其他实体之间的多对多关系。 当我创建一个新的RestrictionElement并合并Element时,RestrictionElement被插入两次。代码:
// element is an Element, restriction is a Restriction. Both are already in present in the database.
RestrictionElement newRestrictionElement = new RestrictionElement(restriction, element);
Transaction transaction = new Transaction();
em.merge(element); //em is the EntityManager
transaction.commit();
但是,如果删除行restriction.getReferencedRestrictionElements().add(this);
,则会插入一次RestrictionElement。
谁能解释为什么会这样?或者指向一个文档,解释如何计算merge()命令的作用?
相关的JPA代码:(我只给出了一小部分。代码没有任何其他大问题。)
public class RestrictionElement {
@JoinColumns({@JoinColumn(name = "ELEMENT_ID", referencedColumnName = "ID"),@JoinColumn(name = "ELEMENT_DESCRIPTOR", referencedColumnName = "DESCRIPTOR")})
private Element element;
@JoinColumns({@JoinColumn(name = "RESTRICTION_ID", referencedColumnName = "ID"),@JoinColumn(name = "RESTRICTION_DESCRIPTOR", referencedColumnName = "DESCRIPTOR")})
private Restriction restriction;
public RestrictionElement(Restriction restriction, Element element) {
this.restriction = restriction;
this.element = element;
restriction.getReferencedRestrictionElements().add(this);
element.getReferingRestrictionElements().add(this);
}
}
public class Element {
@OneToMany(mappedBy = "element")
private List<RestrictionElement> referingRestrictionElements = new ArrayList<RestrictionElement>();
}
public class Restriction extends Element {
@OneToMany(mappedBy = "restriction", cascade = { ALL, PERSIST, MERGE, REMOVE, REFRESH })
private List<RestrictionElement> referencedRestrictionElements = new ArrayList<RestrictionElement>();
}
答案 0 :(得分:2)
你如何坚持RestrictionElement?我的猜测是,当你坚持它时,你会得到一个副本,然后在你将Element与它的引用合并时的第二个。
尝试对新对象使用persist(),并在使用正确的托管副本管理对象后将其关联起来。
答案 1 :(得分:1)
不要忘记,一旦使用JPA检索类的实例,实例就会被管理,对它的任何更改都将自动合并到数据库中。
默认情况下,此合并将在您查询表时发生。因此可能发生以下情况:
在类似于上面的情况下,第二个查找将有效地向第一个表发出合并。 (我不确定这里的细节或情况)。
我的建议是你在开始修改它之前发出每一个查询(例如findById)或每个实例(即set等)。
希望它有所帮助。
答案 2 :(得分:1)
我运行程序时遇到了类似的问题,但问题是一步一步调试。
我通过在OneToMany关系中将List更改为Set来解决了这个问题。