集合未由flush()处理

问题描述 投票:2回答:2

我正在尝试从双向关联中删除子元素。我的说法是,如果我查询Employee实例,然后使用getChildren()方法来获取关联的子代,则父代和子代记录都将得到管理。现在,当我调用child.setParent(null)parent.getChildren().remove(child)时,事务提交时两个更新都应该保留,但是我得到了:org.hibernate.AssertionFailure: collection [org.rand.model.Employee.children] was not processed by flush()异常,除非我在子元素上调用merge或通过查询获取子元素。

有人可以解释为什么会这样吗?

我正在使用休眠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();
    }
}
hibernate jpa jpa-2.0 bean-validation
2个回答
4
投票

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


0
投票

对于我来说,我是通过以下方式解决的:

@PersistenceContext(type = PersistenceContextType.EXTENDED)
  private EntityManager entityManager;
© www.soinside.com 2019 - 2024. All rights reserved.