【发布时间】:2014-07-15 09:53:24
【问题描述】:
我正在尝试从双向关联中删除子元素。我的理解是,如果我查询 Employee 实例,然后使用 getChildren() 方法获取关联的子项,则父子记录都被管理。现在,当我调用 child.setParent(null) 和 parent.getChildren().remove(child) 时,事务提交时这两个更新都应该保持不变,但是我得到:org.hibernate.AssertionFailure: collection [org.rand.model.Employee.children] was not processed by flush() 异常,除非我在子元素上调用合并或通过查询获取子元素。
有人可以解释为什么会这样吗?
我使用的是休眠 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();
}
}
【问题讨论】:
-
它应该被管理,所以检查“em.contains()”。如果它是托管的,那么您永远不需要按 JPA 规范调用合并。如果它不是托管的,那么您必须问一个问题,为什么 Hibernate 分发非托管对象...
标签: hibernate jpa jpa-2.0 bean-validation