javax.persistence.EntityNotFoundException:已删除的实体传递给持久化

Posted

技术标签:

【中文标题】javax.persistence.EntityNotFoundException:已删除的实体传递给持久化【英文标题】:javax.persistence.EntityNotFoundException: deleted entity passed to persist 【发布时间】:2014-11-22 11:38:58 【问题描述】:

我使用 spring + JPA 作为 orm 框架。我的项目层结构类似于 web --> Service --> Domain DAO --> genericDAO。 在 genericDAO 中,我使用 @PersistenceContext 注入 EntityManager。

genericDAO.delete(Object o) 
    o = entityManager.merge(o);
    entityManager.remove(o);


genericDAO.saveOrUpdate(Object o) 
    entityManager.merge(o);
    entityManager.flush();

在服务层的一种方法中,我有以下操作。

// delete order item if already exists.
Order order = getOrderFromSession();
if (CollectionUtils.isNotEmpty(orderItems)) 
  Iterator<OrderItem> iterator = orderItems.iterator();
  while (iterator.hasNext()) 
     OrderItem orderItem = iterator.next();
     iterator.remove();
     orderDAO.deleteOrderItem(orderItem); // Which internall calls genericDAO.delete()
  

//orderDAO.saveOrder(order) // line  Y
//Now create fresh order items submitted by jsp form.
for (ProductVO productVO : productList) 
 if (productVO.getQuantity() > 0) 
    orderItem = new OrderItem();
    Product product = productDAO.getProductByCode(productVO.getCode()); // line X
    orderItem.populateOrderItemByProduct(product, productVO.getQuantity(), order);
    order.addOrderItem(orderItem);
 

第 X 行使用 hql 检索产品实体。但是当执行第 X 行时,我得到以下错误。 :[core.entity.OrderItem#]。

我不明白订单项是否已在实体管理器中标记为已删除,为什么它会尝试保留。

当我取消注释行 Y 时,它在内部刷新实体管理器,它工作正常。我不明白为什么它需要在执行第 X 行之前刷新实体管理器

【问题讨论】:

【参考方案1】:

这是hibernate documentation的引述

事务性持久实例(即加载、保存的对象, 由 Session 创建或查询)可以由 应用程序,并且对持久状态的任何更改都将被持久化 当 Session 被刷新时。无需调用特定方法(如 update(),它具有 不同的目的)使您的修改持久化。最多 更新对象状态的直接方法是 load() 它 然后在 Session 打开时直接操作它。

有时这种编程模型是 效率低下,因为它需要在同一个会话中同时使用 SQL SELECT 加载一个对象和一个 SQL UPDATE 以保持其更新状态。 Hibernate 通过使用分离的实例提供了另一种方法。

但我会尽量简单地解释一下。您的方法getOrderFromSession() 是事务性的,休眠对象在其中打开了会话,但是当对象order 返回给您时,它已与会话分离并且休眠不知道您在用它做什么,直到您坚持他再次。因此,对于已删除的项目,当您保存该对象时,hibernate 会发现,在此之前,处于休眠状态的对象具有与 getOrderFromSession() 返回时相同的状态。

这里有detailed explanation

更新:

当你在 hibernate 中删除对象时,java 中的对象变成瞬态的。它在java中仍然存在,删除后就可以使用了。

Session.delete() 将从数据库中删除对象的状态。您的 但是,应用程序仍然可以保存对已删除对象的引用。 最好将 delete() 视为创建一个持久实例, 瞬态。

【讨论】:

由于实体管理器是共享的,删除订单项目和加载产品发生在同一个实体管理器中。那为什么会报错呢?

以上是关于javax.persistence.EntityNotFoundException:已删除的实体传递给持久化的主要内容,如果未能解决你的问题,请参考以下文章