Java 休眠 saveOrUpdate 行为

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6443672/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 05:58:17  来源:igfitidea点击:

Hibernate saveOrUpdate behavior

javadatabasehibernate

提问by iliaden

Does anyone know how Hibernate knows whether to INSERT or to UPDATE a value in the database when session.saveOrUpdate()is called?

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

So far, I have only determined that it is not dependent on the information in the cache, and that the existence of the entity in the database is determined by the primary key.

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

采纳答案by Rihards

When you use .saveOrUpdate()Hibernate will check if the object is transient (it has no identifier property) and if so it will make it persistent by generating it the identifier and assigning it to session. If the object has an identifier already it will perform .update().

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

From the documentation:

文档

saveOrUpdate() does the following:

saveOrUpdate() 执行以下操作:

  • if the object is already persistent in this session, do nothing
  • if another object associated with the session has the same identifier, throw an exception
  • if the object has no identifier property, save() it
  • if the object's identifier has the value assigned to a newly instantiated object, save() it
  • if the object is versioned by a "version" or "timestamp", and the version property value is the same value assigned to a newly instantiated object, save() it otherwise update() the object
  • 如果该对象已经在此会话中持久存在,则不执行任何操作
  • 如果与会话关联的另一个对象具有相同的标识符,则抛出异常
  • 如果对象没有标识符属性,则 save() 它
  • 如果对象的标识符具有分配给新实例化的对象的值,则 save() 它
  • 如果对象由“版本”或“时间戳”进行版本控制,并且版本属性值与分配给新实例化的对象的值相同,则 save() 否则 update() 对象

回答by Olaf

This is done based on the value of the primary key. If the primary key is undefined, it's value will default to 0 for numeric surrogate keys and savewill be performed. If the primary key is filled out, it will invoke an update.

这是基于主键的值完成的。如果主键未定义,对于数字代理键,其值将默认为 0,save并将执行。如果主键被填写,它将调用一个update.

回答by bpgergo

As stated here, saveOrUpdateeither saves a transient instance by generating a new identifier or updates/reattaches the detached instances associated with its current identifier. More specifically it does:

如所陈述在这里saveOrUpdate无论是通过产生一个新的标识符或更新保存一个瞬态的实例/重新附接具有其当前标识符相关联的分离的实例。更具体地说,它的作用是:

  • if the object is already persistent in this session, do nothing
  • if another object associated with the session has the same identifier, throw an exception
  • if the object has no identifier property, save()it
  • if the object's identifier has the value assigned to a newly instantiated object, save() it
  • if the object is versioned by a <version>or <timestamp>, and the version property value is
  • the same value assigned to a newly instantiated object, save()it
  • otherwise update()the object
  • 如果该对象已经在此会话中持久存在,则不执行任何操作
  • 如果与会话关联的另一个对象具有相同的标识符,则抛出异常
  • 如果对象没有标识符属性,save()
  • 如果对象的标识符具有分配给新实例化的对象的值,则 save() 它
  • 如果对象由<version>或 进行版本控制<timestamp>,并且版本属性值为
  • 分配给新实例化的对象的相同值,save()
  • 否则update()对象

回答by jhegedus

Perhaps it is helpful to quote the Hibernate bible (Java Persistence with Hibernate, 2nd ed., page 528):

也许引用 Hibernate 圣经会有所帮助(Java Persistence with Hibernate,第二版,第 528 页):

More experienced Hibernate users use saveOrUpdate()exclusively; it's much easier to let Hibernate decide what is new and what is old, especially in a more complex network of objects with mixed state. The only (not really serious) disadvantage of exclusive saveOrUpdate()is that it sometimes can't guess whether an instance is old or new without firing a SELECTat the database - for example, when a class is mapped with a natural composite key and no version or timestamp property.

How does Hibernate detect which instances are old and which are new? A range of options is available. Hibernate assumes that an instance is an unsaved transient instance if:

  • The identifier property is null.
  • The version or timestamp property (if it exists) is null.
  • A new instance of the same persistent class, created by Hibernate internally, has the same database identifier values as the given instance.
  • You supply an unsaved-valuein the mapping document for the class, and the value of the identifier property matches. The unsaved-valueattribute is also available for version and timestamp mapping elements.
  • Entity data with the same identifier value isn't in the second-level cache.
  • You supply an implementation or org.hibernate.Interceptorand return Boolean.TRUEfrom Interceptor.isUnsaved()after checking the instance in your code.

更有经验的 Hibernate 用户saveOrUpdate()独占使用;让 Hibernate 决定什么是新的和什么是旧的要容易得多,尤其是在具有混合状态的更复杂的对象网络中。唯一的(不是很严重)的缺点saveOrUpdate()是它有时无法SELECT在不触发数据库的情况下猜测实例是旧的还是新的——例如,当一个类被映射为一个自然复合键并且没有版本或时间戳时财产。

Hibernate 如何检测哪些实例是旧的,哪些是新的?有一系列选项可供选择。在以下情况下,Hibernate 假定实例是未保存的瞬态实例:

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

回答by Jaikrat

If someone not really understood in theory then there is a code

如果有人在理论上没有真正理解,那么有一个代码

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
}