2009-12-19 3 views
1

엔티티 객체가 2 개의 열에 제약 조건이있는 테이블에 매핑되는 MySQL 데이터베이스에 JPA 프로젝트가 연결되어 있습니다. 즉,JPA보고 중복 엔트리가있는 새로운 동일 엔티티 지속

@Entity 
@Table(name = "my_entity") 
class MyEntity { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "id") 
    private Integer id; 
    @Basic(optional = false) 
    @Column(name = "myField1") 
    private String myField1; 
    @Basic(optional = false) 
    @Column(name = "myField2") 
    private int myField2; 
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "myEntity") 
    private Set<OtherEntity> otherEntitySet; 
} 

데이터베이스에서 my_entity 테이블에는 (myField1, myField2)에 대한 고유 제한 조건이 있습니다. 문제는 EntityManager.remove (엔터티)가있는 기존 엔터티를 제거한 다음 EntityManager.persist (엔터티)를 사용하여 새 엔터티를 추가하면 데이터베이스에서 중복 행에 대한 오류가 발생한다는 것입니다. 예를 들어

:

이 나에게이 중복 된 항목 것에 대해 불평 MySQLIntegrityConstraintViolationException을 제공
entityManager.getTransaction().begin(); 

MyEntity entity1 = new MyEntity(); 
entity1.setMyField1("Foo"); 
entity1.setMyField2(500); 
entityManager.persist(entity1); 

entityManager.getTransaction().commit(); 
entityManager.getTransaction().begin(); 

entityManager.remove(entity1); 

MyEntity entity2 = new MyEntity(); 
entity2.setMyField1("Foo"); 
entity2.setMyField2(500); 
entityManager.persist(entity2); 

entityManager.getTransaction().commit(); 

. 이전 항목을 제거하기 전에 새 항목을 추가하려고하기 때문에 그것이라고 생각합니다. 그 명령을 유지할 방법이 있습니까? 또는 JPA를 사용하여 이러한 상황을 방지 할 수있는 방법이 있습니까? 정확히는 일반적인 유스 케이스는 아니지만 모든 관련 데이터를 제거하고 다시 시작하기 위해 엔티티를 삭제하려고 시도한 사용자가 걱정할 필요가 없다면 더 쉬운 필드를 다시 만든 다음 데이터가 제거되지 않았 음을 확인하십시오. 다음과 같이

의 해시 코드와 동일 구현은 다음과 같습니다

public int hashCode() { 
    int hash = 0; 
    hash += (getMyField1().hashCode() + getMyField2()); 
    return hash; 
} 

public boolean equals(Object object) { 
    if (!(object instanceof MyEntity)) { 
     return false; 
    } 
    MyEntity other = (MyEntity) other; 
    return (getMyField2() == other.getMyField2()) && 
     (getMyField1().equals(other.getMyField1())); 
} 
+0

당신이 당신의 등호와 hashCode 구현을 추가 할 수 있습니다 :이 게시물 및 @EmbeddedId을 추가하는 방법에 대한 설명을 참조하십시오? –

+0

추가됨 - 원래 ID 확인을 위해 equals에 지름길이 있었지만 확인을 위해 제거했습니다. 같은 문제. – Jon

답변

2

내가 JPA의 작동 순서를 지정하는 표준 방법이라고 생각하지 않습니다, 그래서 문이 실행됩니다 주문 보장은 없습니다. 이상적으로, JPA 구현은 이러한 상황을 감지하고 삽입 이전에 삭제를 수행 할만큼 충분히 영리 할 것입니다. 그러나 이는 자주 실패하는 영역입니다. 또는 데이터베이스가 지연된 제약 조건 검사를 지원하면 (예 : Oracle은 수행하지만 MySQL은 그렇지 않습니다.), 데이터베이스는 커 L 트 시간까지 고유 제한 조건 위반 예외를 제공 할 때까지 대기하여이를 처리합니다.

그래서 한 가지 해결책은 remove (entity1) 호출 후 추가 커밋을 수행하는 것입니다. 엔티티 2를 생성하기 전에 먼저 데이터베이스에 있는지 확인하고, 존재한다면 엔티티 2를 사용하십시오. 이 두 가지 옵션은 다소 번거롭고 모든 워크 플로에 적합하지 않을 수 있습니다. 현재 JPA 구현에 대한 문서를 파헤쳐 도움이 될 수있는 확장을 제공하는지 확인할 수 있습니다.

+0

이것은 분명히 올바른 방향으로 나를 가리키고 있습니다. 지금은 JPA에 대한 참조를보고 있습니다. (특히 EclipseLink를 사용하고 있습니다.) 삭제 전에 기본적으로 삽입 작업을하고 있습니다. 응용 프로그램은 사용자가 언제든지 저장하거나 취소 할 수 있도록하므로 제거한 후에 커밋을 수행 할 수는 없지만 기본값을 변경하거나 재사용 기능을 구축하려고합니다. – Jon

+0

나는 당신이 말하기를 원한다고 생각합니다 : remove (entity1) 뒤에 명시 적으로'flush()'합니다. 커밋 할 필요가 없습니다. 나쁜 아이디어입니다. (하나의 TRA에 전체적인 방법을 넣는 것이 더 좋습니다) – pihentagy

0

나는 UC와 삽입/삭제가 잘못된 순서로 발생하는 것과 같은 문제가있었습니다. UC의 열과 일치하는 엔티티 용 복합 키를 만들어야했습니다. 그 후 삭제 및 삽입이 올바른 순서로 발생했습니다.

https://forum.hibernate.org/viewtopic.php?p=2382504

+0

일반적인 생각을 갖고 있다고 생각하지만, 구체적인 것은별로 없습니다. 간단한 예를 들려 주시겠습니까? 연락처 정보에 대한 간단한 테이블이 있다면 어떻게 될까요? 나는 사람의 이름 (id int, name varchar)에 대한 데이터베이스의 고유 한 제한 조건을 가지고 있으며 다른 테이블은 해당 ID에 대한 링크입니다. 내 주소록을 편집하고 "오, 나는 이제 더 이상 에디와 친구가 아닙니다."라고 말하면서 다른 관련 데이터와 연계하여 그 항목을 삭제합니다. 그러나 일부 다른 사람들을 업데이트 한 후 (저장하지 않음), 나는 "Eddie"를 다른 누군가의 입장으로 완전히 입력합니다. 디자인 한 JPA에서 오류가 발생합니다. – Jon

관련 문제