【问题标题】:Hibernate - since JPA Listener activation I get "IllegalArgumentException: Removing a detached instance"休眠 - 由于 JPA 侦听器激活我得到“IllegalArgumentException:删除一个分离的实例”
【发布时间】:2016-03-10 06:39:24
【问题描述】:

到目前为止,我使用带有“会话”对象的经典 Hibernate,而不是使用 JPA EntityManager。现在我通过在 META-INF 中激活服务“org.hibernate.jpa.event.spi.JpaIntegrator”来引入JPA Listener/callback 支持。

之后,我在调用“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 监听器激活它工作正常。

我的代码正在从父对象中删除一个对象(分离 - 在事务之外),然后尝试使用新事务保存父对象。孩子归父母所有,所有更改都应该级联?那么我需要做什么或者这是 Hibernate 的错误?

我正在使用 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/:?]

【问题讨论】:

  • 我自己必须解决几十个类似的问题,我可以向您保证,这不是 Hibernate 中的错误,而是您对 Hibernate 工作原理的理解中的错误。在这种情况下,它看起来对我来说,但我不能确定,因为没有足够的代码,就像你试图在事务之外进行删除一样。
  • 但为什么它以前在没有 JPA 侦听器支持激活的情况下工作?您对哪个源代码领域感兴趣?
  • 我花了几个小时但我没有工作。在研究了linklink 之后,我得出结论,这很可能是 Hibernate 的一个错误。对我来说,一个解决方案是使用 JPA 回调 Hibernate Event Lister link

标签: java spring hibernate


【解决方案1】:

我花了几个小时,但我发现它无法使用 JPA 侦听器“org.hibernate.jpa.event.spi.JpaIntegrator”。研究完以下链接

我得出的结论是,这很可能是 Hibernate 的一个错误,因为“saveOrUpdate()”应该完全处理这种情况,如果我不使用“JpaIntegrator”的东西它也可以处理这种情况。我也尝试过使用 Hibernate 4.3.11,同样的问题。

对我来说,一个解决方案是使用特殊的 JPA 监听器激活 Hibernate Event Listener

例如

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

【讨论】:

    猜你喜欢
    • 2018-09-04
    • 1970-01-01
    • 2015-04-05
    • 2012-10-07
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多