Обновление нескольких строк с использованием JPA

Я хочу обновить все поля таблицы, которая имеет значение colame NAME как "PCNAME". Имя таблицы, которую я хочу обновить, это XYZ.I хочу обновить только некоторые поля и не сохранять некоторые неизменные.

Это затронет многие строки, а не одну строку, так как будет много строк с NAME= 'PCNAME' Как я могу это сделать с помощью JPA. У меня есть класс объектов, связанный с этой таблицей.

Ответ 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:

  • массовые обновления обойти оптимистичные проверки блокировки (так что вы должны вручную увеличивать столбец версии и/или вручную проверять столбец версии, если хотите)
  • контекст персистентности не синхронизируется с результатом массовых операций (поэтому массовые операции должны выполняться в отдельной транзакции или в самом начале транзакции перед загрузкой состояния любого объекта, который могут быть затронуты).

Моим предложением было бы, по крайней мере, увеличить столбец версии, чтобы избежать проблемы с concurrency с другими потоками:

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

И выполнить его в отдельной транзакции или перед загрузкой любого XYZ, как описано ранее.

Ссылки

  • Спецификация JPA 1.0
    • Раздел 4.10 "Операции массового обновления и удаления"