Перейти к основному содержимому

@DynamicUpdate в Spring Data JPA

· 3 мин. чтения

1. Обзор

Когда мы используем Spring Data JPA с Hibernate, мы также можем использовать дополнительные функции Hibernate. @DynamicUpdate — одна из таких функций.

@DynamicUpdate — это аннотация уровня класса, которую можно применить к объекту JPA. Это гарантирует, что Hibernate использует только измененные столбцы в операторе SQL, который он генерирует для обновления сущности .

В этой статье мы рассмотрим аннотацию @DynamicUpdate с помощью примера Spring Data JPA .

2. JPA @Entity

Когда приложение запускается, Hibernate генерирует операторы SQL для операций CRUD всех сущностей. Эти операторы SQL генерируются один раз и кэшируются в памяти для повышения производительности.

Сгенерированный оператор обновления SQL включает все столбцы объекта. Если мы обновляем объект, значения измененных столбцов передаются оператору обновления SQL. Для столбцов, которые не обновляются, Hibernate использует их существующие значения для обновления.

Попробуем понять это на примере. Во-первых, давайте рассмотрим сущность JPA с именем Account :

@Entity
public class Account {

@Id
private int id;

@Column
private String name;

@Column
private String type;

@Column
private boolean active;

// Getters and Setters
}

Далее давайте напишем репозиторий JPA для объекта Account :

@Repository
public interface AccountRepository extends JpaRepository<Account, Integer> {
}

Теперь мы будем использовать AccountRepository для обновления поля имени объекта Account :

Account account = accountRepository.findOne(ACCOUNT_ID);
account.setName("Test Account");
accountRepository.save(account);

После выполнения этого обновления мы можем проверить сгенерированный оператор SQL. Сгенерированный оператор SQL будет включать все столбцы Account :

update Account set active=?, name=?, type=? where id=?

3. JPA @Entity с @DynamicUpdate

Мы видели, что хотя мы изменили только поле имени , Hibernate включил все столбцы в инструкцию SQL.

Теперь добавим аннотацию @DynamicUpdate к сущности Account :

@Entity
@DynamicUpdate
public class Account {
// Existing data and methods
}

Затем давайте запустим тот же код обновления, который мы использовали в предыдущем разделе. Мы видим, что SQL, сгенерированный Hibernate, в этом случае включает только столбец имени :

update Account set name=? where id=?

Итак, что происходит, когда мы используем @DynamicUpdate для сущности ?

На самом деле, когда мы используем @DynamicUpdate для объекта, Hibernate не использует кэшированный оператор SQL для обновления. Вместо этого он будет генерировать оператор SQL каждый раз, когда мы обновляем сущность. Этот сгенерированный SQL включает только измененные столбцы .

Чтобы узнать измененные столбцы, Hibernate необходимо отслеживать состояние текущего объекта. Итак, когда мы изменяем какое-либо поле сущности, оно сравнивает текущее и измененное состояния сущности.

Это означает, что с @DynamicUpdate связаны накладные расходы . Поэтому мы должны использовать его только тогда, когда это действительно необходимо.

Конечно, есть несколько сценариев, в которых мы должны использовать эту аннотацию — например, если сущность представляет собой таблицу с большим количеством столбцов, и только некоторые из этих столбцов требуется часто обновлять. Кроме того, когда мы используем оптимистическую блокировку без версии, нам нужно использовать @DynamicUpdate .

4. Вывод

В этом руководстве мы рассмотрели аннотацию @DynamicUpdate для Hibernate. Мы использовали пример Spring Data JPA, чтобы увидеть @DynamicUpdate в действии. Кроме того, мы обсудили, когда нам следует использовать эту функцию, а когда нет.

Как всегда, полные примеры кода, используемые в этом руководстве, доступны на Github .