[SPRING] 키 'PRIMARY'에 대한 중복 항목 'string1-string2'
SPRING키 'PRIMARY'에 대한 중복 항목 'string1-string2'
MySQL 데이터베이스를 통해 hibernate와 jpa를 사용하는 Spring MVC 애플리케이션에서 하위 엔티티를 포함하는 상위 엔티티를 저장할 때마다 하위 엔티티에 대한 다음 오류 메시지가 표시됩니다.
Duplicate entry 'string1-string2' for key 'PRIMARY'
여기서 string1 및 string2는 하위 엔터티의 복합 기본 키의 두 부분을 참조합니다. 이 오류를 어떻게 해결합니까?
엔티티 간의 관계가 상위 주소 엔티티에 정의되는 방식은 다음과 같습니다.
@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;
이 링크를 클릭하면 전체 스택 추적을 볼 수 있습니다. 주소 엔티티에 대한 전체 코드는이 링크에서 찾을 수 있습니다.
GeneralCode 엔티티의 전체 코드는이 링크에서 읽을 수 있습니다.
복합 기본 키 클래스의 코드는이 링크에서 찾을 수 있습니다. Address로 확장 된 BaseEntity 클래스는이 링크에서 찾을 수 있습니다.
이 오류 메시지에 대한 많은 게시물을 읽었습니다. 다른 게시물에 대한 응답으로 내 오류 메시지가 해결되지 않으며 일반적으로 내 엔터티가 복합 기본 키를 사용한다는 사실을 설명하지 않습니다.
주소를 유지하는 코드는 다음과 같습니다.
@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;
이 링크를 클릭하면 새 스택 추적을 읽을 수 있습니다.
이 오류를 어떻게 해결할 수 있습니까?
저장 주소 메서드에 다음 코드를 추가하여 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가 위의 코드가 앱이 충돌하기 직전에 실행 중임을 나타내지 만 여전히 동일한 오류가 발생합니다.
이 링크를 클릭하면 결과 스택 추적을 읽을 수 있습니다.
해결법
-
==============================
1.무엇보다도 먼저 해결해야 할 몇 가지 사항이 있습니다.
무엇보다도 먼저 해결해야 할 몇 가지 사항이 있습니다.
최신 정보
savehl7Address 메소드 :
@Override public void savehl7Address(HL7Address addr) { HL7GeneralCode code = addr.use(); if(code != null && code.getId()==null){ //HL7GeneralCode is not persistent. We don't support that throw new IllegalStateException("Cannot persist an adress using a non persistent HL7GeneralCode"); //In case you'd want to support it //code = em.find(HL7GeneralCode, code.getId()); } //Merge the code without any address info //This will ensure we only reattach the code without triggering the address //transitive persistence by reachability addr.setUse(null); code.getAddresses().remove(addr); code = em.merge(code); //Now set the code to the address and vice-versa addr.setUse(code); code.getAddresses().add(addr); if ((Integer)addr.getId() == null) { System.out.println("[[[[[[[[[[[[ about to persist address ]]]]]]]]]]]]]]]]]]]]"); em.persist(addr); } else { System.out.println("]]]]]]]]]]]]]]]]]] about to merge address [[[[[[[[[[[[[[[[[[[[["); addr = em.merge(addr); } }
-
==============================
2.문제는 CascadeType.ALL 사용 관계에있는 것 같습니다.
문제는 CascadeType.ALL 사용 관계에있는 것 같습니다.
무슨 일이야 ?
해결책 :
사용 관계에 대한 계단식 규칙을 정의하지 않습니다.
@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가 아직 데이터베이스에없는 유스 케이스가있는 경우 특히 손으로 관리해야합니다.
지나치게 단순화 된 솔루션 (문제를 이해할 수 있도록) :
@Override public void savehl7Address(HL7Address addr) { if(addr.use() != null && addr.use().getId()==null){ //HL7GeneralCode is not persistent yet this.em.persist(addr.use()); //since there is a cascade ALL on the adresses relationship addr is now persistent return; } 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);} }
보시다시피이 솔루션은 확실히 생산 준비가 아닌 최고의 것이 아닙니다. 실제 솔루션은 모든 유스 케이스를 연구하고 그에 따라 계단식 규칙 (사용 및 주소 관계 모두에 따라)을 적용하는 것입니다.
제 의견으로는 할 수있는 가장 좋은 방법은 savehl7Address를 호출 할 때 HL7GeneralCode가 이미 영속적으로 유지되도록하는 것입니다. 이렇게하면 더 나은 해결책 일 수 있습니다.
@Override public void savehl7Address(HL7Address addr) { if(addr.use() != null && addr.use().getId()==null){ //HL7GeneralCode is not persistent. We don't support that throw new IllegalStateException("Cannot persist an adress using a non persistent HL7GeneralCode"); } 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);} }
from https://stackoverflow.com/questions/25316761/duplicate-entry-string1-string2-for-key-primary by cc-by-sa and MIT license