合并后无法删除分离的实体()
Cannot delete detached entity after merge()
我在尝试删除实体时遇到问题,这是我的代码:
@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());
}
}
我不太明白为什么,remove语句失败,抛出
java.lang.IllegalArgumentException: Removing a detached instance
entity manager不包含entity,所以每次都会执行merge(),remove总是失败,传递的对象不一样
我是不是做错了什么?
这是捕获异常的 StackTrace:
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)
我看到注解在一个私有方法上,所以它是从 class 中调用的。这是 class @Service class 吗?您能否提供有关内部调用删除函数的方法的更多详细信息。 Spring private/protected 方法忽略事务注释。它们仅支持 public 方法。
编辑
仅仅制作方法public是不够的,bean的入口点是什么(你从哪里调用那个私有方法)?如果该入口方法不是从 spring bean 调用的(例如,从自动装配的字段)并且没有使用 @Transactional 注释,那么这就是问题的原因。
删除之前不需要使用合并,为什么要合并要删除的内容?
而是像下面那样做:
//begin transaction
YourEntity entity = entityManager.getReference(The_Class, The_ID);
entityManager.remove(entity);
我在尝试删除实体时遇到问题,这是我的代码:
@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());
}
}
我不太明白为什么,remove语句失败,抛出
java.lang.IllegalArgumentException: Removing a detached instance
entity manager不包含entity,所以每次都会执行merge(),remove总是失败,传递的对象不一样
我是不是做错了什么?
这是捕获异常的 StackTrace:
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)
我看到注解在一个私有方法上,所以它是从 class 中调用的。这是 class @Service class 吗?您能否提供有关内部调用删除函数的方法的更多详细信息。 Spring private/protected 方法忽略事务注释。它们仅支持 public 方法。
编辑
仅仅制作方法public是不够的,bean的入口点是什么(你从哪里调用那个私有方法)?如果该入口方法不是从 spring bean 调用的(例如,从自动装配的字段)并且没有使用 @Transactional 注释,那么这就是问题的原因。
删除之前不需要使用合并,为什么要合并要删除的内容?
而是像下面那样做:
//begin transaction
YourEntity entity = entityManager.getReference(The_Class, The_ID);
entityManager.remove(entity);