I have a java EE project using JPA (transaction-type="JTA"), hibernate as provider. I write my beans to handle the CRUD things. The program running in JBOSS 7 AS.
I have an EntityManagerDAO :
@Stateful
public class EntityManagerDao implements Serializable {
@PersistenceContext(unitName = "dtdJpa")
private EntityManager entityManager;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public Object updateObject(Object object) {
object = entityManager.merge(object);
return object;
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void createObject(Object object) {
entityManager.persist(object);
}
public void refresh(Object object) {
entityManager.refresh(object);
}
public <T> T find(Class<T> clazz, Long id) {
return entityManager.find(clazz, id);
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void deleteObject(Object object) {
entityManager.remove(object);
}
}
but when I invoke deleteObject
, this exception comes out.
java.lang.IllegalArgumentException: Removing a detached instance com.test.User#5
How is this caused and how can I solve it?
In my experience, if I query an object from the DB then closed the entity manager then do a DB delete, the problem happens. Or if I copy that loaded object to another instance then do a delete, this problem also happens. In my opinion there are 2 things to keep note:
Cheers
Sometimes you can just get id from detached instance, then use direct query to database.As example
After you can clean context
In my case, I got the same error, when I tried to delete an object using,
without creating any transaction before that.
And the problem is solved by creating the transaction first(session.beginTransaction() and then deleting the object.
I hope my answer will help someone :)
I faced the same problem. The detached entity should be re-attached. As @BalusC mentioned, using
EntityManager.merge()
should be used to attach the detached entity.EntityManager.merge()
generates SQL Query which fetches the current state of the entity, on whichEntityManager.remove()
has to be performed. But in my case it didn't worked. TryEntityManager.remove(EntityManager.find(Class<T>,arg))
instead. It worked for me.Sometimes its simply because you are missing the @Transaction annotation for add, remove, update operations.
EntityManager#remove()
works only on entities which are managed in the current transaction/context. In your case, you're retrieving the entity in an earlier transaction, storing it in the HTTP session and then attempting to remove it in a different transaction/context. This just won't work.You need to check if the entity is managed by
EntityManager#contains()
and if not, then make it managed itEntityManager#merge()
.Basically, the
delete()
method of your business service class should look like this: