flush()没有处理集合

时间:2014-07-15 09:53:25

标签: hibernate jpa jpa-2.0 bean-validation

我正在尝试从双向关联中删除子元素。我的理解是,如果我查询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();
    }
}

2 个答案:

答案 0 :(得分:4)

可能是因为在removeChildWithMerge中,您的子集合是延迟加载的,并且在刷新期间,触发加载导致此异常的项目。您可以使用Hibernate.inititalize(obj)而不是调用merge。另一方面,在removeChildWithFetch中,您正在使用fetch来急切加载集合,因此收集项目。因此,在刷新期间,项目已经加载,因此没有问题。

答案 1 :(得分:0)

对于我的情况,我通过以下方式解决了该问题:

@PersistenceContext(type = PersistenceContextType.EXTENDED)
  private EntityManager entityManager;