Hibernate saveOrUpdate行为

ili*_*den 41 java database hibernate

有没有人知道Hibernate在session.saveOrUpdate()调用时是如何知道INSERT还是更新数据库中的值?

到目前为止,我只确定它不依赖于缓存中的信息,并且数据库中实体的存在是由主键确定的.

Rih*_*rds 41

当您使用.saveOrUpdate()Hibernate时,将检查对象是否是瞬态的(它没有标识符属性),如果是,它将通过生成标识符并将其分配给会话来使其持久化.如果对象已经具有标识符,则它将执行.update().

文档:

saveOrUpdate()执行以下操作:

  • 如果对象在此会话中已经持久化,则不执行任何操作
  • 如果与会话关联的另一个对象具有相同的标识符,则抛出异常
  • 如果对象没有标识符属性,则保存()它
  • 如果对象的标识符具有分配给新实例化对象的值,则保存()它
  • 如果对象是由or版本化的,并且version属性值是分配给新实例化对象的相同值,则save()否则update()该对象


jhe*_*dus 10

也许引用Hibernate圣经(Java Persistence with Hibernate,第2版,第528页)是有帮助的:

更有经验的Hibernate用户使用saveOrUpdate(); 让Hibernate决定什么是新的和什么是旧的更容易,特别是在具有混合状态的更复杂的对象网络中.独占的唯一(不是非常严重)缺点saveOrUpdate()是它有时无法猜测实例是旧的还是新的而不SELECT在数据库中触发- 例如,当一个类使用自然复合键映射而没有版本或时间戳时属性.

Hibernate如何检测哪些实例是旧的哪些是新的?有多种选择.Hibernate假定实例是未保存的瞬态实例,如果:

  • 标识符属性是null.
  • 版本或时间戳属性(如果存在)是null.
  • 由Hibernate在内部创建的同一持久化类的新实例具有与给定实例相同的数据库标识符值.
  • unsaved-value在类的映射文档中提供了一个,并且identifier属性的值匹配.该unsaved-value属性也可用于版本和时间戳映射元素.
  • 具有相同标识符值的实体数据不在二级缓存中.
  • 您提供一个实现或org.hibernate.Interceptor与收益Boolean.TRUEInterceptor.isUnsaved()您的代码检查实例之后.

  • 扫描文档不是屏幕可读或可搜索的. (2认同)