我想更新列 NAME 值为“PCNAME”的表的所有字段。我要更新的表名是 XYZ。我只想更新一些字段,而不是保持一些不变。
这将影响很多行而不是单行,因为会有很多行带有 NAME='PCNAME' 我如何使用 JPA 来做到这一点。我有与该表关联的实体类。
您可以使用面向对象的方式或使用更新查询来执行此操作。
面向对象:
public void setNameOfAllEntities(String newname){
List<MyEntity> items =
entityManager.createQuery("from MyEntity", MyEntity.class)
.getResultList();
for(MyEntity entity : items){
entity.setName(newname);
}
}
使用更新查询(未经测试):
public void setNameOfAllEntities(final String newname){
final int changes =
entityManager.createQuery("update MyEntity set name = :name")
.setParameter("name", newname)
.executeUpdate();
System.out.println(changes + " rows changed");
}
显然,第二个版本表现更好。
seanizer 的回答是正确的(+1),批量更新对于这个用例来说确实很好。但是您必须对批量更新操作采取一些预防措施。解释 JPA 规范:
因此,我的建议是至少增加版本列以避免与其他线程的并发问题:
UPDATE XYZ xyz
SET xyz.name = :newname, xyz.version = xyz.version + 1
并在单独的事务中或在加载任何 XYZ 之前执行它,如前所述。
从 Java Persistence 2.1 开始,您可以使用CriteriaUpdate
Criteria API 进行批量更新。
CriteriaUpdate<Entity> criteriaUpdate = builder.createCriteriaUpdate(Entity.class)
.set(root.get("field"), value)
.where(predicates);
int updated = entityManager.createQuery(criteriaUpdate).executeUpdate();
记住:
标准 API 批量更新操作直接映射到数据库更新操作,绕过任何乐观锁定检查。如果需要,使用批量更新操作的便携式应用程序必须手动更新版本列的值,和/或手动验证版本列的值。持久性上下文与批量更新的结果不同步。