使用 EntityManager 进行休眠更新

Posted

技术标签:

【中文标题】使用 EntityManager 进行休眠更新【英文标题】:Hibernate update with EntityManager 【发布时间】:2012-10-17 15:44:07 【问题描述】:

我正在使用 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),这样会更简单、更高效,因为如果实体已经加载,它就不会执行任何查询。 附录:这在文档中有明确的解释。见docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html_single/… 【参考方案1】:

可能会出现两种情况。

您可能想要更改对象的属性,并且只更改该属性。

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

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

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

如果是这种情况你要使用的方法:合并、可选地修改、刷新、提交。

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

【讨论】:

找到了我的解决方案,最后我使用了 entityManager.getTrasaction().begin(); person = entityManager.find(Person.class, id); entityManager.merge(人); // 修改人员数据 entityManager.getTransaction().commit(); 很高兴您找到了解决方案。如果 find(Person.class, id) 期间使用的 id 是执行 merge(person) 时使用的 person.id,则可能不需要合并。完成查找后,您的实体将得到管理,您可以修改和提交更改。【参考方案2】:

如果修改包含在事务中,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 passing to persist: com.application.model.Person 可能您正在使用 EntityManager 的两个不同实例。【参考方案3】:

我不知道你到底在问什么,但是在你的方法中,Person.getPersonById(int id),你可以使用以下代码来简化你的代码:

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

【讨论】:

以上是关于使用 EntityManager 进行休眠更新的主要内容,如果未能解决你的问题,请参考以下文章

使用休眠 sessionFactory 或 JPA entityManager?

06 EntityManager和EntityTransaction

如何使用休眠将mysql与Java连接?例外:没有名为 org.hibernate.tutorial_jpa 的 EntityManager 的持久性提供程序 [关闭]

jdbcTemplate 更新后如何刷新 entityManager 状态

使用 EntityManager / Hibernate 进行批量更新

如何测试休眠通用 dao 模式