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:已删除的实体传递给持久化的主要内容,如果未能解决你的问题,请参考以下文章