【发布时间】:2014-10-08 14:51:29
【问题描述】:
在通过 MySQL 数据库使用 hibernate 和 jpa 的 Spring MVC 应用程序中,每当我尝试保存包含子实体的父实体时,都会收到以下关于子实体的错误消息:
Duplicate entry 'string1-string2' for key 'PRIMARY'
这里,string1和string2指的是子实体的复合主键的两部分。 如何解决此错误?
这里是在父Address实体中定义实体间关系的方式:
@ManyToOne(cascade = { CascadeType.ALL }, fetch=FetchType.EAGER)
@JoinColumns({ @JoinColumn(name = "usecode", referencedColumnName = "code", insertable = false, updatable = false),
@JoinColumn(name = "usecodesystem", referencedColumnName = "codesystem", insertable = false, updatable = false)
})
public HL7GeneralCode use;
这是在子GeneralCode实体中定义关系的方式:
@OneToMany(mappedBy = "use", cascade = {CascadeType.ALL})
private Set<HL7Address> addresses;
完整的堆栈跟踪可以查看by clicking on this link。Address 实体的完整代码可以在 at this link 找到。
GeneralCode 实体的完整代码可以阅读at this link。
复合主键类的代码可以在at this link找到。
而由Address扩展的BaseEntity类可以在at this link找到。
我已经阅读了很多关于此错误消息的帖子。其他帖子的答案无法解决我的错误消息,并且它们通常无法解决我的实体使用复合主键的事实。
编辑:
持久化地址的代码是:
@Override
public void savehl7Address(HL7Address addr) {
if ((Integer)addr.getId() == null) {
System.out.println("[[[[[[[[[[[[ about to persist address ]]]]]]]]]]]]]]]]]]]]");
this.em.persist(addr);}
else {
System.out.println("]]]]]]]]]]]]]]]]]] about to merge address [[[[[[[[[[[[[[[[[[[[[");
this.em.merge(addr);}
}
第二次编辑:
我尝试遵循@Ben75 的建议,但代码在this.em.persist(addr.getUse()); 行崩溃。请注意,他的 if 子句不适合我的实际对象模型,因此我将下面的 if 子句更改为 if(addr.getUse() != null && addr.getId()==null)。这是我的代码。
@Override
public void savehl7Address(HL7Address addr) {
if(addr.getUse() != null && addr.getId()==null){
//this next line prints in the stack trace right before the app crashes
System.out.println("about to this.em.persist(addr.getUse());");
//HL7GeneralCode is not persistent yet
this.em.persist(addr.getUse());
//since there is a cascade ALL on the adresses relationship addr is now persistent
return;
}
System.out.println("=========================== inside jpahl7patientrespository.savehl7Address(addr)");
if ((Integer)addr.getId() == null) {
System.out.println("[[[[[[[[[[[[ about to persist address ]]]]]]]]]]]]]]]]]]]]");
this.em.persist(addr);}
else {
System.out.println("]]]]]]]]]]]]]]]]]] about to merge address [[[[[[[[[[[[[[[[[[[[[");
this.em.merge(addr);}
}
HL7Address的相关部分现在是:
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumns({ @JoinColumn(name = "usecode", referencedColumnName = "code", insertable = false, updatable = false),
@JoinColumn(name = "usecodesystem", referencedColumnName = "codesystem", insertable = false, updatable = false)
})
public HL7GeneralCode use;
HL7GeneralCode的相关部分现在是:
@OneToMany(mappedBy = "use")
private Set<HL7Address> addresses;
可以读取新的堆栈跟踪by clicking on this link。
我该如何解决这个错误?
第三次编辑:
我按照 ben75 的建议在保存地址方法中添加了以下代码:
if(addr.getUse() != null && !this.em.contains(addr.getUse())){
System.out.println("about to this.em.persist(addr.getUse());");
this.em.persist(addr.getUse());return;
}
不幸的是,尽管堆栈跟踪SYSO 表明上述代码在应用程序崩溃之前正在运行,但我仍然遇到相同的错误。
您可以阅读生成的堆栈跟踪by clicking on this link。
【问题讨论】:
-
你的
EntityManager“persist”代码是什么样的? -
@isim 我刚刚将持久代码作为编辑添加到我上面原始帖子的末尾。这对你有帮助吗?
-
所有链接都断开了,这个问题虽然因为答案很好而非常有用,但现在对其他人的用处已减少。不使用外部链接的充分理由。
标签: java spring hibernate jpa hibernate-mapping