使用 JPA 更新多行

2022-09-03 09:17:08

我想更新具有哥伦布名称值为“PCNAME”的表的所有字段。我要更新的表名是XYZ。我只想更新一些字段,而不是保持一些不变。

这将影响许多行而不是单个行,因为会有很多行使用NAME='PCNAME'我如何使用JPA做到这一点。我有与此表关联的实体类。


答案 1

您可以采用面向对象的方式或使用更新查询来执行此操作。

面向对象:

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");

}

显然,第二个版本的性能更好。


答案 2

seanizer的答案是正确的(+1),批量更新对于这个用例来说确实很好。但是,您必须对批量更新操作采取一些预防措施。解释 JPA 规范:

  • 批量更新绕过乐观锁定检查(因此,如果需要,必须手动递增版本列和/或手动验证版本列)
  • 持久性上下文不会与批量操作的结果同步(因此,在加载可能受影响的任何实体的状态之前,应在单独的事务中或在事务的最开始执行批量操作)。

因此,我的建议是至少增加版本列,以避免与其他线程的并发问题:

UPDATE XYZ xyz
SET xyz.name = :newname, xyz.version = xyz.version + 1 

并在单独的事务中或在加载任何 XYZ 之前执行它,如前所述。

引用

  • JPA 1.0 规范
    • 第 4.10 节 “批量更新和删除操作”

推荐