【发布时间】:2011-09-20 13:58:55
【问题描述】:
有谁知道 Hibernate 在调用 session.saveOrUpdate() 时如何知道是插入还是更新数据库中的值?
到目前为止,我只确定它不依赖于缓存中的信息,数据库中实体的存在是由主键决定的。
【问题讨论】:
有谁知道 Hibernate 在调用 session.saveOrUpdate() 时如何知道是插入还是更新数据库中的值?
到目前为止,我只确定它不依赖于缓存中的信息,数据库中实体的存在是由主键决定的。
【问题讨论】:
当您使用.saveOrUpdate() 时,Hibernate 将检查对象是否是瞬态的(它没有标识符属性),如果是,它将通过生成标识符并将其分配给会话来使其持久化。如果对象已经有标识符,它将执行.update()。
saveOrUpdate() 执行以下操作:
【讨论】:
clone()(保持相同的标识符),并修改了一个值。休眠update() 对象。它属于哪个类别?
session.evict()分离的。
如果有人在理论上没有真正理解,那么有一个代码
MyModel sent = myDao.myDaoImpl(id);
if(sent == null){
sent = **new MyModel();** // new Object
sent.setXX(id);
sent.setYY("Yes");
sent.setDate(new Date());
myDao.saveOrUpdate(sent); // Insert will be called
} else if(! "Yes".equalsIgnoreCase(sent.getFlag())) {
sent.setXX("Yes");
sent.setDate(new Date());
myDao.saveOrUpdate(sent); // Update will be called
}
【讨论】:
也许引用 Hibernate 圣经会有所帮助(Java Persistence with Hibernate, 2nd ed.,第 528 页):
更有经验的 Hibernate 用户只使用
saveOrUpdate();让 Hibernate 决定什么是新的和什么是旧的要容易得多,尤其是在具有混合状态的更复杂的对象网络中。独占saveOrUpdate()唯一(不是很严重)的缺点是它有时无法猜测实例是旧的还是新的而不在数据库中触发SELECT- 例如,当一个类被映射到一个自然复合时键,没有版本或时间戳属性。Hibernate 如何检测哪些实例是旧的,哪些是新的?有一系列选项可供选择。 Hibernate 假设一个实例是一个未保存的瞬态实例,如果:
- 标识符属性为
null。- 版本或时间戳属性(如果存在)是
null。- 由 Hibernate 在内部创建的同一持久类的新实例具有与给定实例相同的数据库标识符值。
- 您在类的映射文档中提供
unsaved-value,并且标识符属性的值匹配。unsaved-value属性也可用于版本和时间戳映射元素。- 具有相同标识符值的实体数据不在二级缓存中。
- 在检查代码中的实例后,您提供一个实现或
org.hibernate.Interceptor并从Interceptor.isUnsaved()返回Boolean.TRUE。
【讨论】:
这是根据主键的值完成的。如果未定义主键,则数字代理键的值将默认为 0,并且将执行 save。如果填写了主键,则会调用update。
【讨论】:
如here 所述,saveOrUpdate 要么通过生成新标识符来保存临时实例,要么更新/重新附加与其当前标识符关联的分离实例。更具体地说:
save()它<version> 或<timestamp> 进行版本控制,并且版本属性值为save() itupdate()对象【讨论】: