javax.persistence.EntityNotFoundException: deleted entity passed to persist

I am using spring + JPA as orm framework. My project layer structure is like web --> Service --> Domain DAO --> genericDAO. In genericDAO I am injecting EntityManager using @PersistenceContext.

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

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

In one method in service layer, I have following operations.

// 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);
 }
}

Line X retrieve product entity using hql. But when line X is executed, I get below error. javax.persistence.EntityNotFoundException: deleted entity passed to persist: [core.entity.OrderItem#].

I do not understand if order item is already marked as deleted in entity manager, why it tries to persist.

When I uncomment line Y, which internally flush the entity manager, it works fine. I do not understand why it requires entity manager to be flushed before executing line X

Answers


Here is a quote from hibernate documentation

Transactional persistent instances (i.e. objects loaded, saved, created or queried by the Session) can be manipulated by the application, and any changes to persistent state will be persisted when the Session is flushed. There is no need to call a particular method (like update(), which has a different purpose) to make your modifications persistent. The most straightforward way to update the state of an object is to load() it and then manipulate it directly while the Session is open.

Sometimes this programming model is inefficient, as it requires in the same session both an SQL SELECT to load an object and an SQL UPDATE to persist its updated state. Hibernate offers an alternate approach by using detached instances.

But I'll try to explain simplier. Your method getOrderFromSession() is transactional and hibernate objects have session open inside it, but when object order is returned to you, it has been detached from session and hibernate doesn't know what you are doing with it, until you persist him again. So for deleted items hibernate will find out when you save that object, until then object in hibernate have same state as it was in a moment when getOrderFromSession() has return it.

Here you have detailed explanation

UPDATE:

When you delete object in hibernate, object in java becomes transient. It still exist in java and after delete you can use it.

Session.delete() will remove an object's state from the database. Your application, however, can still hold a reference to a deleted object. It is best to think of delete() as making a persistent instance, transient.


Need Your Help

Mathematica MonomialList Not Working

list wolfram-mathematica

Thank you in advance for any and all help with my problem!

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.