休眠保存或更新行为

2022-09-01 02:36:31

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

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


答案 1

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

文档中

saveOrUpdate() 执行以下操作:

  • 如果对象已在此会话中持久化,则不执行任何操作
  • 如果与会话关联的另一个对象具有相同的标识符,则引发异常
  • 如果对象没有标识符属性,则 save() it
  • 如果对象的标识符具有分配给新实例化对象的值,则 save() 它
  • 如果对象由“version”或“timestamp”进行版本控制,并且 version 属性值与分配给新实例化对象的值相同,则 save() 它以其他方式 update() 对象

答案 2

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

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

休眠如何检测哪些实例是旧的,哪些是新的?有一系列选项可用。休眠假定实例是未保存的瞬态实例,如果出现以下情况:

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

推荐