14

columNAMEの値が「PCNAME」であるテーブルのすべてのフィールドを更新したいと思います。更新したいテーブル名はXYZです。一部のフィールドのみを更新し、一部は変更しないでください。

これは、NAME ='PCNAME'の行が多数あるため、単一の行ではなく、多くの行に影響します。JPAを使用してこれを行うにはどうすればよいですか。このテーブルにエンティティクラスが関連付けられています。

4

3 に答える 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");

}

明らかに、2番目のバージョンの方がパフォーマンスが優れています。

于 2010-11-01T14:06:54.480 に答える
18

seanizerの答えは正解(+1)であり、このユースケースでは一括更新が実際に適しています。ただし、一括更新操作ではいくつかの予防措置を講じる必要があります。JPA仕様を言い換えると:

  • 一括更新は楽観的ロックチェックをバイパスします(したがって、必要に応じて、バージョン列を手動でインクリメントするか、バージョン列を手動で検証する必要があります)
  • 永続コンテキストはバルク操作の結果と同期されません(したがって、バルク操作は、影響を受ける可能性のあるエンティティの状態をロードする前に、別のトランザクションで、またはトランザクションの最初に実行する必要があります)。

したがって、他のスレッドとの同時実行の問題を回避するために、少なくともバージョン列をインクリメントすることをお勧めします。

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

また、別のトランザクションで実行するか、前に説明したようにXYZをロードする前に実行します。

参考文献

  • JPA1.0仕様
    • セクション4.10「一括更新および削除操作」
于 2010-11-01T21:13:29.783 に答える
0

Java Persistence 2.1以降CriteriaUpdate、CriteriaAPIを使用して一括更新を行うために使用できます。

CriteriaUpdate<Entity> criteriaUpdate = builder.createCriteriaUpdate(Entity.class)
     .set(root.get("field"), value)
     .where(predicates);
int updated = entityManager.createQuery(criteriaUpdate).executeUpdate();

覚えておいてください:

Criteria APIの一括更新操作は、楽観的ロックチェックをバイパスして、データベース更新操作に直接マップされます。一括更新操作を使用するポータブルアプリケーションは、必要に応じてバージョン列の値を手動で更新するか、バージョン列の値を手動で検証する必要があります。永続コンテキストは、一括更新の結果と同期されません。

于 2019-12-16T15:15:14.473 に答える