我正在尝试从双向关联中删除子元素。我的理解是,如果我查询Employee实例然后使用getChildren()
方法来获取关联的子项,则管理父记录和子记录。现在,当我调用child.setParent(null)
和parent.getChildren().remove(child)
时,两个更新都应该在事务提交时保持不变,但是我得到:org.hibernate.AssertionFailure: collection [org.rand.model.Employee.children] was not processed by flush()
异常,除非我在子元素上调用merge或者通过查询获取子节点。
有人可以解释为什么会这样吗?
我正在使用hibernate 3.5.6-Final
由于
更新:经过一段时间的调试后,我发现导致此错误的代码,我必须在发布问题时意外删除它。我真诚地为此道歉。
罪魁祸首是自定义OneToManyInverseCheck
bean验证器,它验证父和子是否都设置了关系。这是在提交操作期间触发加载其他实体(子项的子项)。
实体:
@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:
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();
}
}
答案 0 :(得分:4)
可能是因为在removeChildWithMerge中,您的子集合是延迟加载的,并且在刷新期间,触发加载导致此异常的项目。您可以使用Hibernate.inititalize(obj)而不是调用merge。另一方面,在removeChildWithFetch中,您正在使用fetch来急切加载集合,因此收集项目。因此,在刷新期间,项目已经加载,因此没有问题。
答案 1 :(得分:0)
对于我的情况,我通过以下方式解决了该问题:
@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;