양방향 연관에서 하위 요소를 제거하려고합니다. 필자의 말은 Employee 인스턴스를 쿼리 한 다음 getChildren()
메서드를 사용하여 연결된 자식을 가져 오는 경우 부모 및 자식 레코드가 모두 관리된다는 것입니다. 이제 child.setParent(null)
및 parent.getChildren().remove(child)
을 호출하면 트랜잭션이 커밋 될 때 두 업데이트가 유지되어야하지만 자식 요소에 병합을 호출하거나 쿼리로 자식을 페치하지 않는 한 org.hibernate.AssertionFailure: collection [org.rand.model.Employee.children] was not processed by flush()
예외가 발생합니다.컬렉션이 flush()에 의해 처리되지 않았습니다.
누군가가 왜 그런지 설명 할 수 있습니까? 디버깅 동안 나는이 오류를 일으키는 코드를 발견하고 내가 실수로이 질문을 게시하는 동안 제거해야한다 후 :
나는
UPDATE
3.5.6-최종감사를 최대 절전 모드 사용하고 있습니다. 진심으로 사과드립니다.
부모와 자녀 모두에 관계가 설정되어 있는지 확인하는 커스텀bean validator입니다. 이것은 커밋 작업 중 추가 엔터티 (자식 하위)로드를 트리거했습니다.
법인 :
@Entity
public class Employee {
@Id
@GeneratedValue(strategy=GenerationType.TABLE)
private int id;
@Version
private int version;
private String name;
@ManyToOne
private Employee parent;
@OneToMany(mappedBy="parent")
@OneToManyInverseCheck(inverseFieldName="parent")
private List<Employee> children;
//get/set methods ommitted
}
간단한 JUnit을 : 당신의 자식 컬렉션이 예외가 발생 항목의 로딩을 트리거,로드 및 플러시 동안 게으른 때문에 removeChildWithMerge에
public class JPAUpdate {
private static EntityManagerFactory emf;
private EntityManager em;
@BeforeClass
public static void init() {
emf = Persistence.createEntityManagerFactory("myapp-db");
}
@Before
public void setUp() throws Exception {
em = emf.createEntityManager();
}
@Test
public void removeChildWithMerge() {
em.getTransaction().begin();
Employee e = em.createQuery("from Employee e where e.children is not empty order by e.id asc", Employee.class).getResultList().get(0);
Employee child = e.getChildren().get(0);
child.setParent(null);
e.getChildren().remove(child);
// removing this merge causes org.hibernate.AssertionFailure: collection [org.rand.model.Employee.children] was not processed by flush()
em.merge(child);
em.getTransaction().commit();
}
@Test
public void removeChildWithFetch() {
em.getTransaction().begin();
Employee e = em.createQuery("from Employee e left join fetch e.children where e.children is not empty order by e.id asc", Employee.class).getResultList().get(0);
Employee child = e.getChildren().get(0);
child.setParent(null);
e.getChildren().remove(child);
//em.merge(child); - no merge needed
em.getTransaction().commit();
}
@Test
public void removeChild() {
em.getTransaction().begin();
Employee e = em.createQuery("from Employee e left join fetch e.children where e.children is not empty order by e.id asc", Employee.class).getResultList().get(0);
Employee child = e.getChildren().get(0);
child.setParent(null);
e.getChildren().remove(child);
//em.merge(child); - no merge needed
em.getTransaction().commit();
}
}
관리해야하므로 "em.contains()"를 선택하십시오. 관리되는 경우에는 JPA 스펙에 의해 병합을 호출 할 필요가 없습니다. 그것이 관리되지 않는다면 당신은 왜 Hibernate가 관리되지 않는 객체를 나눠주고 있는지에 대한 질문을해야한다 ... –