merge()后无法删除分离的实体

时间:2015-03-09 16:27:59

标签: java spring hibernate jpa

我在尝试删除实体时遇到问题,这是我的代码:

  @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());
    }
  }

我真的不明白为什么,但删除声明失败,抛出

java.lang.IllegalArgumentException: Removing a detached instance

实体管理器不包含实体,因此每次都执行merge(),并且删除总是失败,并传递不同的对象。

我做错了吗?

以下是捕获的异常的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)

2 个答案:

答案 0 :(得分:1)

我看到注释是在一个私有方法上,所以它是从类中调用的。这个类是@Service类吗?您能否提供有关内部调用删除功能的方法的更多详细信息。对于私有/受保护方法,将忽略Spring Transactional注释。它们仅支持公共方法。

修改

仅仅使方法公开是不够的,进入bean的入口点是什么(从哪里调用该私有方法)?如果没有从spring bean调用该入口方法(例如,来自autowired字段)并且它没有使用@Transactional注释,那么这就是问题的原因。

答案 1 :(得分:1)

在删除之前不需要使用合并,为什么要合并要删除的内容?

而不是像下面这样做:

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