Hibernate是* NOT *抛出异常(我认为它应该)

时间:2009-06-03 20:30:26

标签: java hibernate

Hibernate JavaDoc指出Session.update(Object o)如果已经有o的持久化实例会引发异常,对吧?

If there is a persistent instance with the same identifier, an exception is thrown.

但是,以下代码在运行时不会抛出任何内容。我认为应该这样做!

Email email = new Email("andre", "girafa", "hi");

Session session = factory.openSession();
Transaction tx = session.beginTransaction();

session.save(email);
session.update(email);
session.update(email);

tx.commit();

// didn't throw... Let's try again

tx = session.beginTransaction();

session.update(email);
session.update(email);

tx.commit();
session.close();

// still nothing! :(

正如你所说,两次我尝试做多个update(),但是Hibernate对我很轻松。

任何人都有预感为什么?

编辑它似乎只会在另一个等效对象时抛出,例如,email2email具有相同的ID。我想文档有点草率。

4 个答案:

答案 0 :(得分:8)

在SQL语言中,Hibernate中的更新不是UPDATE。 Hibernate处理SQL UPDATE 通过Session对象中的状态缓存自动

但它仅适用于当前会话中加载的实体。此方法 session.update(object)用于将对象从另一个层附加到当前会话以跟踪,并可能在最后更新。

在你的情况下,它只是一个NOOP。如果出现这种情况,那将会非常糟糕:

Email email = new Email("andre", "girafa", "hi");

Session session = factory.openSession();
Transaction tx = session.beginTransaction();

int id = session.save(email);
Email anotherEmail = new Email("", "", "");
anotherEmail.id = id;

session.update(anotherEmail);    // will throw

您可以在Hibernate reference上阅读有关更新方法语义的更多信息。

答案 1 :(得分:6)

没有错误,因为它与您正在更新的实例相同。

如果会话中存在DIFFERENT持久性实例并且您尝试更新(),则会引发错误。

答案 2 :(得分:0)

你可以试试session.flush()吗?查看是否会引发异常(有时提交可能不会刷新数据,具体取决于刷新模式)。

虽然我会说只有当对象在当前会话范围之外更新时才抛出异常,但是请说并发客户端。

答案 3 :(得分:0)

我建议您始终坚持使用EntityManager.merge而不是Hibernate update方法,update令人困惑。

我发现这个article的解释很清楚,我经常参考。

  

与persist and save一样,更新方法是“原始”的Hibernate   在添加合并方法之前很久就存在的方法。它的   语义在几个关键点上有所不同:

     
      
  • 它作用于传递的对象(其返回类型为void); update方法将传递的对象从分离的对象转变为持久的对象
      州;
  •   
  • 如果您将其传递给瞬态实体,则此方法将引发异常。
  •   
     

在以下示例中,我们保存对象,然后逐出(分离)该对象   从上下文中,然后更改其名称并调用更新。注意我们   不要将更新操作的结果放在单独的变量中,   因为更新发生在人员对象本身上。基本上   我们将现有实体实例重新附加到持久性上   上下文-JPA规范不允许我们这样做。

Person person = new Person();
person.setName("John");
session.save(person);
session.evict(person);

person.setName("Mary");
session.update(person);
  

尝试在瞬态实例上调用update会导致   例外。以下内容将不起作用:

Person person = new Person();
person.setName("John");
session.update(person); // PersistenceException!

为了理解上面的部分,您需要了解transientdetached对象之间的区别。