I\'ve got a DAO that I used to load and save my domain objects using JPA. I finally managed to get the transaction stuff working, now I\'ve got another issue.
In my
I suspect that you are running your code outside a transaction so your find
and delete
operations occur in a separate persistence context and the find
actually returns a detached instance (so JPA is right and you ARE deleting a detached object).
Wrap your find / delete sequence inside a transaction.
Update: Below an excerpt of the chapter 7.3.1. Transaction Persistence Context:
If you use an
EntityManager
with a transaction persistence context model outside of an active transaction, each method invocation creates a new persistence context, performs the method action, and ends the persistence context. For example, consider using theEntityManager.find
method outside of a transaction. TheEntityManager
will create a temporary persistence context, perform the find operation, end the persistence context, and return the detached result object to you. A second call with the same id will return a second detached object.
+1 to Pascal Thivent's post and just a followup.
@Transactional
public void remove(long purchaseId){
Purchase attached = jpaTemplate.find(Purchase.class,purchaseId);
jpaTemplate.remove(attached);
}
What worked for me was calling flush so the changes are made as in the following example:
@PersistanceContext
EntityManager em;
public SomeObject(...parameters){
repository.save();
em.flush();
repository.delete();
}
Transaction ensures the ACID properties but not whether the entity is attached or detached.
Even if you are running entityManager.find
and entityManager.remove()
in the same transaction , there is not guarantee that the entity will be attached. So before issuing entityManager.remove()
check if the entity is attached, if not attach it using enitityManger.merge(entity)
and then issue entityManager.remove
on it as follows:
@Transactional
public void delete (long id)
{
ModelObj modelObj=entityManager.find(ModelObj.class,id);
modelObj=entityManager.contains(modelObj)?modelObj:entityManager.merge(modelObj);
em.remove (modelObj);
}
Get the instance by using em.getReference()
instead of em.find()
.
For instance, try:
em.remove(em.getReference(INTFC.class, id));
public void remove(Object obj){
em.remove(em.merge(obj));
}
The above code is similar to that proposed by zawhtut