我使用spring + JPA作为orm框架。我的项目层结构就像web - >服务 - >域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行时,我得到以下错误。 javax.persistence.EntityNotFoundException:传递给persist的已删除实体:[core.entity.OrderItem#]。
我不明白订单项是否已在实体管理器中标记为已删除,为什么它会尝试保留。
当我取消注释内部冲洗实体管理器的第Y行时,它工作正常。我不明白为什么在执行第X行之前需要刷新实体管理器
答案 0 :(得分:1)
事务持久化实例(即加载,保存的对象, 由Session创建或查询)可以被操作 应用程序,持久状态的任何更改都将保留 当会话被刷新时。无需调用特定方法(如update(),具有 一个不同的目的)使你的修改持久。最多 更新对象状态的直接方法是load()它 然后在Session打开时直接操作它。
有时这种编程模型是 效率低下,因为它需要在同一个会话中同时使用SQL SELECT 加载对象和SQL UPDATE以保持其更新状态。 Hibernate通过使用分离的实例提供了另一种方法。
但我会尝试解释更简单。你的方法getOrderFromSession()
是事务性的,而hibernate对象在其中打开会话,但是当对象order
返回给你时,它已经从会话中分离出来了,而hibernate不知道你在做什么,直到你再次坚持下去因此,对于已删除的项目,hibernate将在您保存该对象时找到,直到那时hibernate中的对象具有与getOrderFromSession()
返回它时的状态相同的状态。
<强>更新强>
在hibernate中删除对象时,java中的对象变为瞬态。它仍然存在于java中,删除后你可以使用它。
Session.delete()将从数据库中删除对象的状态。您的 但是,应用程序仍然可以保存对已删除对象的引用。 最好将delete()视为制作持久化实例, 瞬变。