DocKuro
DocKuro

Reputation: 444

Cannot delete detached entity after merge()

I have a problem trying to remove an entity, here's my code:

  @Transactional
  private <K> void delete(String type, EntityWithId<K> entity) {
    try {
      em.remove(em.contains(entity) ? entity : em.merge(entity));
    } catch (Exception e) {
      logger.warn("Unable to delete " + type + " with id " + entity.getId());
    }
  }

I don't really understand why, but the remove statement fails, throwing

java.lang.IllegalArgumentException: Removing a detached instance

The entity manager does not contains the entity, so the merge() is executed every time, and the remove always fails, with different Objects passed.

Am I doing something wrong?

Here is the StackTrace for the caught Exception:

Unable to delete log with id 14091612
java.lang.IllegalArgumentException: Removing a detached instance myproj.jpa.AdvertisementLog#14091612
    at org.hibernate.ejb.event.EJB3DeleteEventListener.performDetachedEntityDeletionCheck(EJB3DeleteEventListener.java:67)
    at org.hibernate.event.internal.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:107)
    at org.hibernate.event.internal.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:74)
    at org.hibernate.internal.SessionImpl.fireDelete(SessionImpl.java:822)
    at org.hibernate.internal.SessionImpl.delete(SessionImpl.java:801)
    at org.hibernate.ejb.AbstractEntityManagerImpl.remove(AbstractEntityManagerImpl.java:880)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
    at com.sun.proxy.$Proxy59.remove(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
    at com.sun.proxy.$Proxy59.remove(Unknown Source)
    at myproj.batch.impl.DeleteOldAdvertisementsImpl.delete(DeleteOldAdvertisementsImpl.java:93)
    at myproj.batch.impl.DeleteOldAdvertisementsImpl.deleteAll(DeleteOldAdvertisementsImpl.java:86)
    at myproj.batch.impl.DeleteOldAdvertisementsImpl.deleteAll(DeleteOldAdvertisementsImpl.java:80)
    at myproj.batch.impl.DeleteOldAdvertisementsImpl.deleteAd(DeleteOldAdvertisementsImpl.java:69)
    at myproj.batch.impl.DeleteOldAdvertisementsImpl.clean(DeleteOldAdvertisementsImpl.java:54)
    at myproj.batch.main.DeleteOldAdvertisementsMain.main(DeleteOldAdvertisementsMain.java:13)

Upvotes: 2

Views: 1692

Answers (2)

zoostar
zoostar

Reputation: 132

I see the annotation is on a private method, so its being called from within the class. Is this class a @Service class? Can you provide more details about the method that internally is calling your delete function. Spring Transactional annotations are ignored for private/protected methods. They are only supported for public methods.

EDIT

It's not enough to just make the method public, what is the entry point into the bean (from where did you call that private method)? If that entry method isn't called from a spring bean (for instance, from an autowired field) and it isn't annotated with @Transactional, then that's the cause of your problem.

Upvotes: 1

uaiHebert
uaiHebert

Reputation: 1912

You do not need to use merge before remove, why are you merging something that you want to delete?

Instead just do like below:

//begin transaction
YourEntity entity = entityManager.getReference(The_Class, The_ID);
entityManager.remove(entity);

Upvotes: 1

Related Questions