Reputation: 444
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
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
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