使用JPA更新多行

时间:2010-11-01 13:57:36

标签: java jpa openjpa

我想更新表格的所有字段,其值为colums NAME为“PCNAME”。 我想要更新的表名是XYZ。我想只更新一些字段而不保持一些不变。

这会影响很多行而不是单行,因为会有很多行,其中NAME ='PCNAME' 我怎样才能使用JPA.I有与此表关联的实体类。

3 个答案:

答案 0 :(得分:21)

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

面向对象:

public void setNameOfAllEntities(String newname){
    List<MyEntity> items =
        entityManager.createQuery("from MyEntity", MyEntity.class)
            .getResultList();
    for(MyEntity entity : items){
        entity.setName(newname);
    }
}

使用Update Query(未经测试):

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

}

显然,第二版表现更好。

答案 1 :(得分:16)

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

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

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

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

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

参考

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

答案 2 :(得分:0)

从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();

请记住:

  

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