【问题标题】:Hibernate giving org.hibernate.NonUniqueObjectException and saving obsolete object to the databaseHibernate 给出 org.hibernate.NonUniqueObjectException 并将过时的对象保存到数据库
【发布时间】:2014-03-12 16:00:43
【问题描述】:

我的服务类中有以下代码。作为功​​能的一部分,此代码被两种不同的方法调用两次。

        //Some code here... 
        LOG.info("###Inside customer interceptor");
        try
        {
            customerDao.save(customer);

        }
        catch (final Exception exp)
        {
        //some code here too...
        }

当第一次从第一个方法调用并执行时,我可以看到在tomcat控制台中打印了一条select SQL语句,但是没有我预期的更新SQL语句(可能是因为Hibernate没有'不要立即发出插入/更新)。 立即从第二种方法再次调用此代码块时,我在 tomcat 控制台中看到一条 SQL 选择语句,然后是一条 SQL 更新语句,然后立即看到一个大胖 org.hibernate.NonUniqueObjectException。 据我所知,这是因为早期的实体仍然附加到会话而不是提交给数据库。

但是,当我去查看数据库时,我发现保存在数据库中的值是第一次调用的对象,而不是我预期的第二个对象。这是正常的还是我在这里遗漏了什么?

我正在使用 Spring 的注解(@Transactional)驱动的事务策略。

【问题讨论】:

标签: java spring hibernate spring-transactions


【解决方案1】:

我宁愿使用.merge(customer) 方法或.saveOrUpdate(customer) 方法来执行这个操作。

  • 如果您使用.merge,您将不会收到非唯一异常,因为它会用您刚刚传递的对象覆盖会话中的对象。
  • 在哪里执行saveOrUpdate,会话不应该有 您尝试更新的对象的同一实例,否则您会收到此 nonUniqueObject 异常。

因为你使用的是spring @Transactional,所以事务应该在完成方法执行后提交。

【讨论】:

  • 感谢宙斯。是的,出于测试目的,我尝试按照其他帖子的建议使用 merge(),它确实保存了新对象而不是过时的对象,并且我没有收到 nonUniqueObject 异常。然而,我的问题更多的是要理解为什么尽管在方法级别使用了@Transactional,为什么它在方法执行结束后没有提交,其次为什么过时的对象在调用 save 方法而不是当前的方法时保存在数据存储中.
  • 我可能需要了解如何拨打电话来回答您的问题。如果使用相同的会话来更新具有相同 ID 的两个客户对象,那么您将获得该异常非唯一异常。在您的代码中的某处,会话没有关闭,所以第一次保存时,没有错误,第二次它给出错误,因为会话已经有该对象。此外,save 用于存储瞬态对象而不是分离对象。
  • 嗯...我在 Hybris 电子商务平台中使用此代码,并且此代码位于 Interceptor 类中,只要与此拦截器相关的模型发生任何更改,就会触发该类。另外,我正在使用 hibernate 的 googlecode 实现,其中 save() 正是 saveOrUpdate() 在其他 Hibernate 实现中所做的。
  • 不知道spring@Transactional是不是用来关闭google版hibernate的session,spring不会自动支持all,你可能要查看ths链接才知道支持ORM 工具在这里docs.spring.io/spring/docs/3.0.x/spring-framework-reference/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-30
  • 1970-01-01
  • 1970-01-01
  • 2020-02-03
相关资源
最近更新 更多