0

@OneToMany 매핑을 업데이트하려고하는 시점에서 멈추었습니다.@OneToMany 컬렉션을 업데이트하는 중 문제가 발생했습니다.

문제점 : 나는 엔티티가 2 개 있습니다. 기준 및 태스크. 기준에는 여러 작업이 포함될 수 있습니다.

class Criteria { 
    @OneToMany(mappedBy = "criteria", cascade = { CascadeType.PERSIST, 
    CascadeType.MERGE, CascadeType.REFRESH }, fetch = FetchType.LAZY) 
    @Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE, 
       org.hibernate.annotations.CascadeType.ALL, 
       org.hibernate.annotations.CascadeType.MERGE, 
       org.hibernate.annotations.CascadeType.PERSIST }) 
    private Set<Task> tasks; 
} 

class Task { 
    @ManyToOne 
    @JoinColumn(name = "CRITERIA_ID", nullable=false) 
    private Criteria criteria; 
} 

새로운 기준으로 기존 기준을 업데이트하려고합니다. 이를 위해서는 기존의 모든 작업을 제거하고 새 작업을 추가해야합니다.

criteriaDao.persist(criteria); 
Set<Task> existingTasks=criteria.getTasks(); 
if(existingTasks != null) { 
    for (Task task : existingTasks) { 
     task.setCriteria(null); 
    } 
    criteria.setTasks(tasks); 
    //more code which sets criteria for each task - this works if i try to save new criteria with new tasks 
} 

Hibernate는 예외를 던지고있다 : 여기 내가 뭐하는 거지 어떻게는 기존 작업을 제거하지 않았기 때문에

Caused by: java.sql.BatchUpdateException: ORA-00001: unique constraint (CCA_DEV_5.TASK__UN) violated 

이 예외가 발생합니다. 난 단지 모든 작업을 삭제하면

, 그것은 완벽하게 작동 아래 코드를 사용하여 주어진 기준에 대한 모든 작업 제거 :

criteriaDao.persist(criteria); 
Set<Task> existingTasks=criteria.getTasks(); 
if(existingTasks != null) { 
    for (Task task : existingTasks) { 
    task.setCriteria(null); 
} 
} 

내가 새 작업과 더 많은 물건을 추가 한 후 병합하여 모든 옵션을 시도를하지만, 아무것도 나를 위해 일하는 것 같다. 나는 여기에 심하게 붙어서 Hibernate에서 아주 기본적인 것을 놓치고있다.

미리 감사드립니다.

답변

0

Task 클래스에는 Criteria에 대한 참조가 전혀 없어야합니다. 주석과 함께 제거하십시오.

그런 다음, 더 이상 존재하지 않고이 참조 같이 Task에 의해 참조 Criteria를 설정하는 단지 criteria.setTasks(newTasks)를 사용하지 않고 criteria을 저장합니다.


조금 설명해 드리겠습니다. CriteriaTask 사이의 관계는 명백히 Criteria 1 --- n Tasks-1 내지 n이다. 이제 one-to-many 관계로 전화 할 수 있으며 귀하의 관점에 따라 many-to-one이라고 부를 수 있습니다. 보기의 Criteria보기에서 그것은 one-to-many, Task의 관점에서 보면 - 그것은 many-to-one입니다. 일반적으로 중 하나를 선택하는 것이 더 바람직하고 직관적이며 입니다. 관점을 선택하면 모든 수정 사항을 적용해야하는 관계를 "제어"하는 엔티티를 정의합니다. 귀하의 경우에는

, 당신은 CriteriaTask의 세트를 소유 또는 를 포함 으로 간주하는 경우 - 당신이 one-to-many으로 관계를 치료하는 것입니다. 결정한 후에는 참조 Task 인 Java 클래스에 필요하지 않습니다. 당신은 Criteria API (DB에 Task에 대해 생성 된 테이블이 있지만 그 테이블에 포함 된 테이블에 Criteria을 포함하는 테이블이 있음)만을 사용하여 관계를 제어합니다.

+0

흠 ... 제 의견으로는 일대 다 (many-to-one)로 일해야합니다. 아무런 문제가 없습니다. 또한 JPA는 역 매핑을 지원합니다.새 세트 콜렉션으로 콜렉션을 설정하기 전에 다음 라인을 추가하여이 문제를 해결했습니다. (작업 태스크 : existingTasks) { task.setCriteria (null);에 대한 ; } => session.flush(); criteria.setTasks (tasks); 이렇게하면 삽입하기 전에 delete 문이 실행됩니다. –

+0

@ RakeshSinha 당신이 문제를 해결해 준 것은 대단한 일입니다. 그러나, 나는 당신이 [이 짧은 부모 - 자식 동면 문서 예제] (http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#example-parentchild-bidir) 이는 one-to-many 관계에서'inverse'를 사용하는 방법을 설명합니다. – yair

+0

감사합니다. 과거에이 문서를 보았습니다. 내가하는 일을 성취 할 다른 방법이 있다고 생각하니? flush()를 명시 적으로 호출하면 작동하지만 엔티티 관리자가 모든 쿼리를 Db로 플러시합니다. 컬렉션을 업데이트하는 더 좋은 방법이 있습니까? –