使用 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 实现会自动管理实体的状态并将其保存到数据库中。您不需要显式调用merge
或update
方法。
如果您使用的是资源本地事务(不由 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 状态