让我们看一下作为朋友的狗和猫的简单例子。这种情况并非罕见。它还有一个比我的商业案例更有趣的好处。
我们想要一个名为“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值”错误?我只是在这里猜测,但我认为这是因为狗还在会议中。
如果这些例子都不起作用,我会理解,但请解释原因。
答案 0 :(得分:4)
现在,假设我想使用示例A或示例B来保存我的朋友一分钟。一个比另一个更好用吗?
两个例子都可以使用(例如B,Hibernate会flush the session before query executions所以它会在选择之前插入狗)但是当你已经拥有时,我没有看到做额外选择(例子B)的重点狗的实例。我只想举例如A。
此外,示例B不会让臭名昭着的“not-null属性引用null或transient值”错误?
否(见上文)。在例子B中,狗不再是短暂的。在示例A中,插入将按正确的顺序完成。
我只是在这里猜测,但我认为这是因为狗还在参加会议。
第一级缓存(会话)用于按id查找,这不是这里的情况。
答案 1 :(得分:2)
saveOrUpdate()执行以下操作:
如果对象在此会话中已经持久化,则不执行任何操作
如果与会话关联的另一个对象具有相同的标识符,则抛出异常
如果对象没有标识符属性,则保存()它
如果对象的标识符具有分配给新实例化对象的值,则保存()它
如果对象是由or版本化的,并且version属性值是分配给新实例化对象的相同值,则保存()它
否则更新()对象
性能明智我会说,因为你没有打开与数据库的连接,所以指定fido指向的对象的引用会更快。
答案 2 :(得分:2)
两者都能正常工作,但效率不同。在B下,因为它执行查询,它不仅具有查询本身的开销,而且它强制hibernate刷新对数据库的更改 - 在事务提交之前可能已保留在内存中的更改,并且发送给许多其他变化。
与数据库的连接通常会遇到相当高的延迟,因此批处理可以同时发送许多更改,从而减少每个语句的延迟。将更改集分解为许多小的更改会导致每个语句的开销相对较高,而不是更大的更改组。因此,最好在可能的情况下一起提交更改。