更新JPA实体中的一个字段

All*_*lan 10 jpa

我有一个User在一个函数中被赋予系统特权的实体.我有一个网页,您可以从下拉列表中选择用户并将表单提交给服务器.在服务器端,我想只更新该实体的一个字段.

我的用户实体将具有除了设置的一个字段及其id之外的所有对象的默认值.我是否需要findById更新特定字段然后进行合并,或者有没有办法告诉只更新该字段?

Pas*_*ent 9

我是否需要执行findById然后更新特定字段然后执行合并

这将是常规方法,除了您不需要合并托管实体,只需让JPA检测更改并自动更新它.

或者有没有办法告诉只更新该字段?

不.但你可以使用你的"短"版本User(只有字段更新).另一个选择是使用批量更新操作,但这是IMO真的不是一个好的用例.我不会用这种方法.

参考

  • JPA 1.0规范
    • 4.10批量更新和删除操作

  • @geoaxis,`@Entity @Table(name ="USER")类ShortUser {...}`将是一个与`User`映射到同一个表的实体,但只有一个列的子集.它应该是不可改变的.请参阅[此问题/答案](http://stackoverflow.com/questions/1667930/2-jpa-entities-on-the-same-table). (4认同)

Pau*_*Wee 8

JPA 2.1现在支持更新标准,允许您通过部分更新实体javax.persistence.criteria.CriteriaUpdate<T>.

Javadoc 在这里.

示例代码:

EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();

// create user
em.getTransaction().begin();
User user = new User();
user.setUsername("user@example.com");
user.setPassword("password");
user.setCreatedAt(new Date());
em.persist(user);
em.getTransaction().commit();
// end create user

assert user.getId() != 0;

System.out.println("Before update user Date of Birth: " + user.getDateOfBirth());

// update user date of birth
em.getTransaction().begin();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaUpdate<User> updateCriteria = cb.createCriteriaUpdate(User.class);
Root<User> root = updateCriteria.from(User.class);
// update dateOfBirth property
updateCriteria.set(root.get("dateOfBirth"), new Date());
// set where clause
updateCriteria.where(cb.equal(root.get("id"), user.getId()));
// update
int affected = em.createQuery(updateCriteria).executeUpdate();
System.out.println("Affected row: " + affected);
em.getTransaction().commit();
// end update user date of birth


// select user again to verify
em.getTransaction().begin();
em.refresh(user);

System.out.println("After update User Date of Birth: " + user.getDateOfBirth());

em.getTransaction().commit();
em.close();
Run Code Online (Sandbox Code Playgroud)

关于JPA 2.1部分更新的更多细节.

  • `CriteriaUpdate` 不是解决这个问题的好方法。它专为**批量更新**操作而设计,因此它绕过了任何乐观锁定检查。文档还说:*持久性上下文与批量更新的结果不同步*。 (2认同)