columNAMEの値が「PCNAME」であるテーブルのすべてのフィールドを更新したいと思います。更新したいテーブル名はXYZです。一部のフィールドのみを更新し、一部は変更しないでください。
これは、NAME ='PCNAME'の行が多数あるため、単一の行ではなく、多くの行に影響します。JPAを使用してこれを行うにはどうすればよいですか。このテーブルにエンティティクラスが関連付けられています。
オブジェクト指向の方法で行うか、更新クエリを使用して行うことができます。
オブジェクト指向:
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をロードする前に実行します。
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の一括更新操作は、楽観的ロックチェックをバイパスして、データベース更新操作に直接マップされます。一括更新操作を使用するポータブルアプリケーションは、必要に応じてバージョン列の値を手動で更新するか、バージョン列の値を手動で検証する必要があります。永続コンテキストは、一括更新の結果と同期されません。