Hibernate - 自从JPA Listener激活后我得到了#Il; IllegalArgumentException:删除一个分离的实例"

时间:2016-03-10 06:39:25

标签: java spring hibernate

到目前为止,我使用了经典的Hibernate和#34; Session"对象而不使用JPA EntityManager。现在我通过激活服务" org.hibernate.jpa.event.spi.JpaIntegrator"来介绍JPA Listener/callback支持。在我的META-INF。

之后我在电话会议期间得到" session.saveOrUpdate()"这个错误。我添加的监听器是在另一个类上,如果我删除那里的" EntityListeners" JPA注释,错误仍然出现。

 java.lang.IllegalArgumentException: Removing a detached instance Attribute#233800
    at org.hibernate.jpa.event.internal.core.JpaDeleteEventListener.performDetachedEntityDeletionCheck(JpaDeleteEventListener.java:69)

没有这个JPA Listener激活它工作正常。

我的代码是从父项中删除对象(已分离 - 在事务外部),然后尝试使用新事务保存父项。孩子由父母拥有,所有的变化都应该级联?那么我需要做什么或者这是一个Hibernate的Bug?

我正在使用Hibernate v4.3.10

我添加的监听器是在另一个类上,如果我删除了注释,错误仍然会出现。

执行代码

    Model model = modelDAO.getModelByCode("1234567");
    model.removeAttribute("Description");
    modelDAO.saveModel(model);  

ModelDAO的实施

   protected Session getSession() {
      return sessionFactory.getCurrentSession();
   }

    protected void beginTransaction() {
      Session session = getSession();
      Transaction transaction = session.getTransaction();
      if (!transaction.isActive()) {
          transaction.begin();
      }
    }

    protected void handleTransaction() {
      if (!bulkHandling) {
          commitTransaction();
      }
    }

    protected void commitTransaction() {
       Session session = getSession();
       Transaction transaction = session.getTransaction();
       if (transaction.isActive()) {
           transaction.commit();
       }
    }

    protected void saveObject(Object obj) {
    if(obj != null) {
        try {
            Session session = getSession();
            beginTransaction();
            if (!session.contains(obj)) {
                session.saveOrUpdate(obj);
            } 
            handleTransaction();
        } catch (Exception ex) {
            logger.error(ex.getMessage(),ex);
            rollbackTransaction();
            throw new HandledOneERPException(ex);
        }
    }
  }

模特&映射

  @Entity
  public class Model extends AbstractERPEntity implements Translateable {

    @OneToMany(cascade = CascadeType.ALL, fetch=FetchType.LAZY, orphanRemoval=true)
    @JoinTable(name = "model_attributes", joinColumns = @JoinColumn(name = "model_id"), inverseJoinColumns = @JoinColumn(name = "attribute_id"))
    @MapKey(name = "name")
    private Map<String, Attribute<?>> attributes = new HashMap<String, Attribute<?>>();

完整堆栈跟踪

 java.lang.IllegalArgumentException: Removing a detached instance     ch.megloff.one.erp.model.attribute.Attribute#233800
  at org.hibernate.jpa.event.internal.core.JpaDeleteEventListener.performDetachedEntityDeletionCheck(JpaDeleteEventListener.java:69) ~[hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.event.internal.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:106) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.internal.SessionImpl.fireDelete(SessionImpl.java:965) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.internal.SessionImpl.delete(SessionImpl.java:909) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.engine.internal.Cascade.deleteOrphans(Cascade.java:437) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:410) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:319) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:296) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:118) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:86) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.cascadeOnUpdate(DefaultSaveOrUpdateEventListener.java:375) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:349) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:244) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:109) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:684) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:676) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:671) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_65]
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_65]
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_65]
  at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_65]
  at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:356) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
  at com.sun.proxy.$Proxy70.saveOrUpdate(Unknown Source) ~[?:?]
  at ch.megloff.common.dao.AbstractHibernateDAO.saveObject(AbstractHibernateDAO.java:261) [classes/:?]

1 个答案:

答案 0 :(得分:0)

我花了几个小时但是我没有使用JPA Listener&#34; org.hibernate.jpa.event.spi.JpaIntegrator&#34;。在研究了以下链接后

我得出的结论是,这最像是一个Hibernate的错误,因为&#34; saveOrUpdate()&#34;如果我不使用&#34; JpaIntegrator&#34;它应该处理这种情况。东西。我也试过Hibernate 4.3.11,同样的问题。

我的解决方案是使用特殊的JPA Listener激活Hibernate Event Listener

e.g。

@Component
@Log4j2
public class HibernateEventListener implements PostCommitDeleteEventListener {

@Autowired
@Qualifier("hibernateOneERPSessionFactory")
private SessionFactory sessionFactory;

@Autowired
private ThreadPoolTaskExecutor taskExecutor;

@Autowired
private TranslationDAO translationDAO;

@PostConstruct
public void registerListeners() {

    taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
    taskExecutor.setAwaitTerminationSeconds(Integer.MAX_VALUE); 

   final EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory)
            .getServiceRegistry().getService(EventListenerRegistry.class);
    registry.appendListeners(EventType.POST_COMMIT_DELETE, this);
}

@Override
public void onPostDelete(PostDeleteEvent event) {
    Object obj = event.getEntity();
    if(obj instanceof Translateable) {
        Translateable translateable = (Translateable)obj;
        if (translateable.hasTranslation()) {
            Runnable task = new Runnable() {
                 public void run()  {
                    translationDAO.deleteUnusedTranslations();
                 }
            };
            taskExecutor.initialize();
            taskExecutor.execute(task);
            taskExecutor.shutdown();
        }
    }
}
}