使用JPA更新多行

问题描述 投票:11回答:3

我想将表的列名称为'PCNAME'的表的所有字段更新。我要更新的表名是XYZ。我只想更新某些字段,而不要保留某些字段。

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

java jpa openjpa
3个回答
22
投票

您既可以使用面向对象的方式,也可以使用更新查询。

面向对象:

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

}

显然,第二个版本表现更好。


17
投票

seanizer的answer是正确的(+1),对于此用例而言,批量更新的确不错。但是,对于批量更新操作,必须采取一些预防措施。释义JPA规范:

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

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

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

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

参考

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

0
投票

自Java Persistence 2.1起,您可以使用CriteriaUpdate使用Criteria API进行批量更新。

CriteriaUpdate

请紧记:

Criteria API批量更新操作直接映射到数据库更新操作,而绕开了任何乐观锁定检查。如果需要,使用批量更新操作的可移植应用程序必须手动更新version列的值,和/或手动验证version列的值。持久性上下文与批量更新的结果不同步。

© www.soinside.com 2019 - 2024. All rights reserved.