Hibernate使用EntityManager进行更新

11

我正在使用Hibernate 4.1.7并尝试更新对象,但没有文档说明应该如何完成。目前,我正在执行以下操作:

    Person person = personDao.getPersonById(1);
    person.setAge(23);
    person.setLastname("McName");
    person = personDao.update(person);

在 PersonDao 中更新看起来像:

    public Person update(Person person) {
      return entityManager.merge(person);
    }

在 PersonDao 中,getPersonById 是:

    public Person getPersonById(int id) {
      personQuery = entityManager.createNamedQuery("Person.findPerson", Person.class);
      personQuery.setParameter("id", id);
      return personQuery.getSingleResult();
    }

我已经在Person类中定义了一个命名查询,代码如下:

    @NamedQuery(name="Person.findPerson", query="SELECT p FROM Person p WHERE p.id = :id")

如果我不想更新我的Person对象,我该如何使用Hibernate实现更新操作?


以上代码是正确的,但是如果所有操作都在一个事务中运行,则对personDao.update()的调用完全是不必要的:JPA/Hibernate会在事务结束时自动将实体状态持久化。getPersonById方法也可以简化为em.find(Person.class, id),这样更简单、更高效,因为如果实体已经被加载,它就不会执行任何查询。 - JB Nizet
附录:这在文档中有详细解释。请参见http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html_single/#d5e772。 - JB Nizet
3个回答

12

你可能会遇到两种情况。

一种情况是你只想修改对象的某个属性。

如果是这种情况,你需要使用以下方法:find、modify、flush、commit。

em.find(Person.class, person.getId())
person.setStatus("ACTIVE");
em.commit();//implicitly flushes if flush mode is COMMIT or AUTO.

您可能希望使用对象属性来更新项目。

如果是这种情况,您可以使用方法:merge,可选修改,flush,commit。

em.merge(person);
//modify person if you wish.
em.commit();//implicitly flushes if flush mode is COMMIT or AUTO.

终于找到了我的解决方案,最终我使用了以下代码: entityManager.getTransaction().begin(); person = entityManager.find(Person.class, id); entityManager.merge(person); // 修改人员数据 entityManager.getTransaction().commit(); - Timo
很高兴你找到了解决方案。如果在find(Person.class, id)期间使用的id与执行merge(person)时使用的person.id相同,则可能不需要进行合并操作。一旦完成查找,您的实体就会被管理,并且您可以修改和提交更改。 - dseibert

1
Hibernate和其他JPA实现会自动管理实体的状态,并在事务中包含修改时将其保存到数据库。您不需要显式调用mergeupdate方法。
如果您正在使用资源本地事务(不由JTA事务管理器管理),请尝试以下操作:
EntityTransaction tx = entityManager.getTransaction();
tx.begin();
Person person = personDao.getPersonById(1);
person.setAge(23);
person.setLastname("McName");
tx.commit();

所有的修改都将自动保存在数据库中。

如果您正在使用JTA,则必须以其他方式标记事务边界,例如使用Spring AOP @Transactional注释。


我正在使用hsqldb(resource-local),但是使用此代码时,我会收到异常:org.hibernate.PersistentObjectException: detached entity passed to persist: com.application.model.Person。 - Timo
可能你正在使用两个不同的EntityManager实例。 - Jarek

0

我不确定你具体在问什么,但是在你的方法中,Person.getPersonById(int id),你可以使用以下代码简化:

return entityManager.find(Person.class, id);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接