了解Hibernate saveOrUpdate和持久性生命周期

时间:2010-06-15 19:54:37

标签: java hibernate

让我们看一下作为朋友的狗和猫的简单例子。这种情况并非罕见。它还有一个比我的商业案例更有趣的好处。

我们想要一个名为“saveFriends”的函数,它带有一个狗名和一个猫名。我们将拯救狗,然后拯救猫。为了这个例子的工作,猫将有一个参考回狗。我知道这不是一个理想的例子,但它很可爱,适用于我们的目的。

FriendService.java

public int saveFriends(String dogName, String catName) {
    Dog fido = new Dog();
    Cat felix = new Cat();

    fido.name = dogName;
    fido = animalDao.saveDog(fido);

    felix.name = catName;
    [ex.A]felix.friend = fido;
    [ex.B]felix.friend = animalDao.getDogByName(dogName);
    animalDao.saveCat(felix);
}

AnimalDao.java (扩展HibernateDaoSupport)

public Dog saveDog(Dog dog) {
    getHibernateTemplate().saveOrUpdate(dog);
    return dog
}

public Cat saveCat(Cat cat) {
    getHibernateTemplate().saveOrUpdate(cat);
    return cat;
}

public Dog getDogByName(String name) {
    return (Dog) getHibernateTemplate().find("from Dog where name=?", name).get(0);
}

现在,假设我想使用示例A或示例B来保存我的朋友一分钟。一个比另一个更好用吗?

此外,示例B不会让臭名昭着的“not-null属性引用null或transient值”错误?我只是在这里猜测,但我认为这是因为狗还在会议中。

如果这些例子都不起作用,我会理解,但请解释原因。

3 个答案:

答案 0 :(得分:4)

  

现在,假设我想使用示例A或示例B来保存我的朋友一分钟。一个比另一个更好用吗?

两个例子都可以使用(例如B,Hibernate会flush the session before query executions所以它会在选择之前插入狗)但是当你已经拥有时,我没有看到做额外选择(例子B)的重点狗的实例。我只想举例如A。

  

此外,示例B不会让臭名昭着的“not-null属性引用null或transient值”错误?

否(见上文)。在例子B中,狗不再是短暂的。在示例A中,插入将按正确的顺序完成。

  

我只是在这里猜测,但我认为这是因为狗还在参加会议。

第一级缓存(会话)用于按id查找,这不是这里的情况。

答案 1 :(得分:2)

来自hibernate

的文档
  

saveOrUpdate()执行以下操作:

     

如果对象在此会话中已经持久化,则不执行任何操作

     

如果与会话关联的另一个对象具有相同的标识符,则抛出异常

     

如果对象没有标识符属性,则保存()它

     

如果对象的标识符具有分配给新实例化对象的值,则保存()它

     

如果对象是由or版本化的,并且version属性值是分配给新实例化对象的相同值,则保存()它

     

否则更新()对象

性能明智我会说,因为你没有打开与数据库的连接,所以指定fido指向的对象的引用会更快。

答案 2 :(得分:2)

两者都能正常工作,但效率不同。在B下,因为它执行查询,它不仅具有查询本身的开销,而且它强制hibernate刷新对数据库的更改 - 在事务提交之前可能已保留在内存中的更改,并且发送给许多其他变化。

与数据库的连接通常会遇到相当高的延迟,因此批处理可以同时发送许多更改,从而减少每个语句的延迟。将更改集分解为许多小的更改会导致每个语句的开销相对较高,而不是更大的更改组。因此,最好在可能的情况下一起提交更改。