java 分离的对象在hibernate中是如何工作的

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5260297/
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-10-30 10:16:27  来源:igfitidea点击:

How does the detached object work in hibernate

javahibernatespring

提问by JB Nizet

I know that object is in detached state when we already hit save and we have to re-attach it.

当我们已经点击保存并且我们必须重新附加它时,我知道该对象处于分离状态。

Suppose i have one form with html text fields and there is save button which saves the text in database.

假设我有一个带有 html 文本字段的表单,并且有一个将文本保存在数据库中的保存按钮。

i have thise code

我有这个代码

 public void edit(Person person) {
  logger.debug("Editing existing person");

  // Retrieve session from Hibernate
  Session session = sessionFactory.getCurrentSession();

  // Retrieve existing person via id
  Person existingPerson = (Person) session.get(Person.class, person.getId());

  // Assign updated values to this person
  existingPerson.setFirstName(person.getFirstName());
  existingPerson.setLastName(existingPerson.getLastName());
  existingPerson.setMoney(existingPerson.getMoney());

  // Save updates
  session.save(existingPerson);
 }

Now i can hit save any number of time to save the data.

现在我可以点击保存任意数量的时间来保存数据。

Now does that mean that once i hit save first time , it becomes detached. So do i need to do something special for that or it does not matter.

现在这是否意味着一旦我第一次点击 save ,它就会变得分离。所以我需要为此做一些特别的事情还是没关系。

I want to know under what condition i need to program anything about detached state

我想知道在什么条件下我需要对有关分离状态的任何内容进行编程

回答by JB Nizet

As soon as the session used to save, load, get or find an entity has been closed, the entity becomes detached. This means that it's not connected anymore to a session, and works like any other POJO.

一旦用于保存、加载、获取或查找实体的会话关闭,实体就会分离。这意味着它不再连接到会话,并且像任何其他 POJO 一样工作。

When an entity is attached and you change one of its properties, Hibernate automatically saves the changes you made to the corresponding row in the database (at flush/commit time).

当附加实体并且您更改其属性之一时,Hibernate 会自动保存您对数据库中相应行所做的更改(在刷新/提交时)。

When it's detached, the changes you made to the object are not saved automatically to the database. In order to save the changes, you need to do it yourself, by calling the session.update() or session.merge(). Both methods do more or less the same thing, but do it differently. I personnally prefer using merge, which is less dangerous and leads to less bugs.

分离时,您对对象所做的更改不会自动保存到数据库中。为了保存更改,您需要自己通过调用 session.update() 或 session.merge() 来完成。这两种方法或多或少做相同的事情,但做的事情不同。我个人更喜欢使用合并,它不那么危险并且导致更少的错误。

Read http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#objectstate-detachedfor more details

阅读http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#objectstate-detached了解更多详情

In your code, the person passed as argument to the edit method is probably detached. What you're doing is getting the person with the same ID as the one passed from the session. existingPersonis thus attached. Then you copy all the properties from the detached person to the attached existingPerson. And finally, you save the existingPerson.

在您的代码中,作为参数传递给编辑方法的人可能是分离的。您正在做的是获取与会话中传递的 ID 具有相同 ID 的人。existingPerson就这样附上了。然后将所有属性从分离的人员复制到附加的 existingPerson。最后,您保存了 existingPerson。

There are 3 problems with this code :

这段代码有 3 个问题:

  1. save doesn't do what you think it does. save is for inserting a new person object. Your existing person already exists and already has an ID, so the operation to use is update or merge.
  2. You don't even need to use update or merge, because since existingPerson is attached to the session, the changes you make (setFirstName, setLastName, etc.) will automatically be made persistent by Hibernate at flush time. It's transparent.
  3. The algorithm you have implemented is the same one (except for cascades, etc.) as the one used by merge, which does all this automatically for you.
  1. save 不会做你认为它会做的事情。save 用于插入一个新的 person 对象。您现有的人已经存在并且已经有一个 ID,所以要使用的操作是更新或合并。
  2. 您甚至不需要使用更新或合并,因为因为 existingPerson 附加到会话,您所做的更改(setFirstName、setLastName 等)将在刷新时由 Hibernate 自动持久化。它是透明的。
  3. 您实现的算法与合并使用的算法相同(除了级联等),它会自动为您完成所有这些工作。

It should thus be changed to :

因此应改为:

public void edit(Person person) {
  logger.debug("Editing existing person, which is a detached object");

  // Retrieve session from Hibernate
  Session session = sessionFactory.getCurrentSession();

  // Retrieve existing person via id, then copy everything from detached person 
  // to attached one, and return attached one
  Person existingPerson = (Person) session.merge(person);
}