【问题标题】:updating multiple rows using JPA使用 JPA 更新多行
【发布时间】:2011-05-03 10:35:24
【问题描述】:

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

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

【问题讨论】:

    标签: java jpa openjpa


    【解决方案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 的 answer 是正确的 (+1) 并且批量更新对于这个用例来说确实很好。但是您必须对批量更新操作采取一些预防措施。套用 JPA 规范:

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

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

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

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

      参考文献

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

      【讨论】:

      • 嗨帕斯卡,这个答案和您的 cmets 以上是否适用于 JPA 2.0?我的应用程序需要做一些乐观的锁定检查。提前致谢。
      • 嗨@arthur,我刚刚对GlassFish 4.1/EclipseLink 2.5.2/JPA 2.1 进行了批量更新,发现批量更新中自动使用了版本字段(即@Version),例如“UPDATE ... SET version = (version + ?), fieldToBeUpdate = ...”和“?”必然为1。我想知道为什么会这样,也许可以预见在某些情况下会发生不止一个版本的计数器增加。但是持久化上下文同步的危险当然仍然存在。
      【解决方案3】:

      从 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 批量更新操作直接映射到数据库更新操作,绕过任何乐观锁定检查。如果需要,使用批量更新操作的便携式应用程序必须手动更新版本列的值,和/或手动验证版本列的值。持久化上下文与批量更新的结果不同步。

      【讨论】:

        猜你喜欢
        • 2017-02-05
        • 2011-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-15
        • 1970-01-01
        • 2020-03-23
        相关资源
        最近更新 更多