Аннотации @PreRemove и @PostRemove
Аннотации @PreRemove и @PostRemove используются в Java Persistence API (JPA) для указания методов обратного вызова (callback), которые выполняются до и после удаления сущности из базы данных. Они находятся в пакете javax.persistence (или jakarta.persistence в Jakarta EE).
@PreRemove: Метод, аннотированный @PreRemove, вызывается перед тем, как сущность будет удалена из базы данных (перед выполнением remove).
@PostRemove: Метод, аннотированный @PostRemove, вызывается после того, как сущность была успешно удалена из базы данных (после выполнения remove).
Эти аннотации полезны для выполнения дополнительной логики, например, очистки зависимых данных, логирования или отправки уведомлений, до или после удаления сущности.
Параметры и настройки
Аннотации @PreRemove и @PostRemove не принимают параметров. Они применяются к методам сущности, которые должны быть вызваны в соответствующий момент жизненного цикла сущности.
Требования к методам:
Метод должен быть void и не принимать параметров.
Метод может иметь любой модификатор доступа (public, protected, private).
Метод не должен быть статическим.
Пример использования:
Жизненный цикл
@PreRemove:
Вызывается перед выполнением операции remove в EntityManager.
Используется для выполнения действий перед удалением, например, очистки зависимых данных или валидации.
Пример: удаление связанных записей в других таблицах, проверка условий удаления.
@PostRemove:
Вызывается после успешного выполнения операции remove и фиксации транзакции.
Используется для выполнения действий после удаления, например, логирования или отправки уведомлений.
Пример: логирование ID удаленной сущности, отправка события в систему сообщений.
Кастомизация событий:
Если требуется более сложная обработка событий, можно использовать @EntityListeners для определения слушателей сущностей.
Пример использования @EntityListeners:
Варианты настройки
Использование в сущности:
Методы @PreRemove и @PostRemove можно определить непосредственно в сущности.
Использование @EntityListeners:
Для разделения логики можно вынести методы обратного вызова в отдельный класс и использовать @EntityListeners.
Глобальные слушатели:
Для применения логики ко всем сущностям можно зарегистрировать глобальный слушатель через Hibernate.
Пример глобального слушателя:
Регистрация глобального слушателя в Hibernate:
#Java #Training #Hard #Spring #SpringDataJPA #PreRemove #PostRemove
Аннотации @PreRemove и @PostRemove используются в Java Persistence API (JPA) для указания методов обратного вызова (callback), которые выполняются до и после удаления сущности из базы данных. Они находятся в пакете javax.persistence (или jakarta.persistence в Jakarta EE).
@PreRemove: Метод, аннотированный @PreRemove, вызывается перед тем, как сущность будет удалена из базы данных (перед выполнением remove).
@PostRemove: Метод, аннотированный @PostRemove, вызывается после того, как сущность была успешно удалена из базы данных (после выполнения remove).
Эти аннотации полезны для выполнения дополнительной логики, например, очистки зависимых данных, логирования или отправки уведомлений, до или после удаления сущности.
Параметры и настройки
Аннотации @PreRemove и @PostRemove не принимают параметров. Они применяются к методам сущности, которые должны быть вызваны в соответствующий момент жизненного цикла сущности.
Требования к методам:
Метод должен быть void и не принимать параметров.
Метод может иметь любой модификатор доступа (public, protected, private).
Метод не должен быть статическим.
Пример использования:
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@PreRemove
private void beforeRemove() {
System.out.println("Before removing user: " + this.name);
// Логика перед удалением
}
@PostRemove
private void afterRemove() {
System.out.println("User removed with ID: " + this.id);
// Логика после удаления
}
}
Жизненный цикл
@PreRemove:
Вызывается перед выполнением операции remove в EntityManager.
Используется для выполнения действий перед удалением, например, очистки зависимых данных или валидации.
Пример: удаление связанных записей в других таблицах, проверка условий удаления.
@PostRemove:
Вызывается после успешного выполнения операции remove и фиксации транзакции.
Используется для выполнения действий после удаления, например, логирования или отправки уведомлений.
Пример: логирование ID удаленной сущности, отправка события в систему сообщений.
Кастомизация событий:
Если требуется более сложная обработка событий, можно использовать @EntityListeners для определения слушателей сущностей.
Пример использования @EntityListeners:
@Entity
@EntityListeners(UserListener.class)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
public class UserListener {
@PreRemove
public void beforeRemove(User user) {
System.out.println("Before removing user: " + user.getName());
}
@PostRemove
public void afterRemove(User user) {
System.out.println("User removed with ID: " + user.getId());
}
}
Варианты настройки
Использование в сущности:
Методы @PreRemove и @PostRemove можно определить непосредственно в сущности.
Использование @EntityListeners:
Для разделения логики можно вынести методы обратного вызова в отдельный класс и использовать @EntityListeners.
Глобальные слушатели:
Для применения логики ко всем сущностям можно зарегистрировать глобальный слушатель через Hibernate.
Пример глобального слушателя:
public class GlobalEntityListener {
@PreRemove
public void beforeRemove(Object entity) {
System.out.println("Before removing entity: " + entity.getClass().getSimpleName());
}
@PostRemove
public void afterRemove(Object entity) {
System.out.println("Entity removed: " + entity.getClass().getSimpleName());
}
}
Регистрация глобального слушателя в Hibernate:
spring.jpa.properties.hibernate.ejb.event.pre-remove=com.example.GlobalEntityListener
spring.jpa.properties.hibernate.ejb.event.post-remove=com.example.GlobalEntityListener
#Java #Training #Hard #Spring #SpringDataJPA #PreRemove #PostRemove
Теперь переходим к рассмотрению аннотаций Spring Data JPA.
Аннотация @Query
Аннотация @Query используется в Spring Data JPA для определения пользовательских JPQL (Java Persistence Query Language) или нативных SQL-запросов непосредственно в репозиторных интерфейсах. Она позволяет гибко настраивать запросы к базе данных, не полагаясь на автоматически генерируемые методы Spring Data. Аннотация находится в пакете org.springframework.data.jpa.repository.
Параметры аннотации
value (обязательный):
Тип: String.
Описание: Содержит JPQL или SQL-запрос. Если запрос JPQL, он должен соответствовать синтаксису JPA. Если это нативный SQL-запрос, необходимо указать параметр nativeQuery = true.
Пример:
nativeQuery (необязательный):
Тип: boolean.
Значение по умолчанию: false.
Описание: Указывает, является ли запрос нативным SQL-запросом. Если true, запрос выполняется как сырой SQL-запрос.
Пример:
countQuery (необязательный):
Тип: String.
Описание: Используется для указания запроса, который будет выполнен для подсчета общего количества записей при использовании пагинации. Актуально только для нативных запросов.
Пример:
name (необязательный):
Тип: String.
Описание: Указывает имя именованного запроса, который должен быть определен в метаданных JPA (например, в orm.xml или через аннотацию @NamedQuery).
Пример:
countName (необязательный):
Тип: String.
Описание: Указывает имя именованного запроса для подсчета количества записей. Используется вместе с name.
Пример:
Жизненный цикл аннотации
Инициализация:
Аннотация @Query обрабатывается во время инициализации Spring-контекста. Spring Data JPA анализирует репозиторные интерфейсы и создает прокси-объекты для методов, помеченных @Query.
Выполнение:
Когда метод репозитория вызывается, Spring Data JPA выполняет запрос, указанный в @Query. Если запрос JPQL, он преобразуется в SQL с помощью JPA-провайдера (например, Hibernate). Если запрос нативный, он выполняется напрямую.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации запросов.
Механизмы Spring, связанные с @Query
Spring Data JPA:
Spring Data JPA предоставляет реализацию репозиториев, которая автоматически обрабатывает аннотацию @Query. Она интегрируется с JPA-провайдером (например, Hibernate) для выполнения запросов.
JPA-провайдер:
JPA-провайдер (например, Hibernate) отвечает за преобразование JPQL-запросов в SQL и их выполнение. Для нативных запросов JPA-провайдер передает SQL напрямую в базу данных.
Транзакционность:
По умолчанию методы репозитория выполняются в транзакции. Это можно настроить с помощью аннотации @Transactional.
Варианты настройки
Использование именованных запросов:
Вместо указания запроса непосредственно в @Query, можно использовать именованные запросы, определенные в orm.xml или через @NamedQuery.
Пагинация и сортировка:
Методы с @Query могут поддерживать пагинацию и сортировку, если возвращают Page, Slice или List с параметром Pageable.
Проекции:
Можно использовать проекции DTO для возврата только необходимых полей:
Динамические запросы:
Для сложных запросов можно использовать JpaSpecificationExecutor или Querydsl.
#Java #Training #Hard #Spring #SpringDataJPA #Query
Аннотация @Query
Аннотация @Query используется в Spring Data JPA для определения пользовательских JPQL (Java Persistence Query Language) или нативных SQL-запросов непосредственно в репозиторных интерфейсах. Она позволяет гибко настраивать запросы к базе данных, не полагаясь на автоматически генерируемые методы Spring Data. Аннотация находится в пакете org.springframework.data.jpa.repository.
Параметры аннотации
value (обязательный):
Тип: String.
Описание: Содержит JPQL или SQL-запрос. Если запрос JPQL, он должен соответствовать синтаксису JPA. Если это нативный SQL-запрос, необходимо указать параметр nativeQuery = true.
Пример:
@Query("SELECT u FROM User u WHERE u.email = ?1")
User findByEmail(String email);
nativeQuery (необязательный):
Тип: boolean.
Значение по умолчанию: false.
Описание: Указывает, является ли запрос нативным SQL-запросом. Если true, запрос выполняется как сырой SQL-запрос.
Пример:
@Query(value = "SELECT * FROM users WHERE email = ?1", nativeQuery = true)
User findByEmail(String email);
countQuery (необязательный):
Тип: String.
Описание: Используется для указания запроса, который будет выполнен для подсчета общего количества записей при использовании пагинации. Актуально только для нативных запросов.
Пример:
@Query(value = "SELECT * FROM users WHERE active = true",
countQuery = "SELECT COUNT(*) FROM users WHERE active = true",
nativeQuery = true)
Page<User> findActiveUsers(Pageable pageable);
name (необязательный):
Тип: String.
Описание: Указывает имя именованного запроса, который должен быть определен в метаданных JPA (например, в orm.xml или через аннотацию @NamedQuery).
Пример:
@Query(name = "User.findByEmail")
User findByEmail(String email);
countName (необязательный):
Тип: String.
Описание: Указывает имя именованного запроса для подсчета количества записей. Используется вместе с name.
Пример:
@Query(name = "User.findActiveUsers", countName = "User.countActiveUsers")
Page<User> findActiveUsers(Pageable pageable);
Жизненный цикл аннотации
Инициализация:
Аннотация @Query обрабатывается во время инициализации Spring-контекста. Spring Data JPA анализирует репозиторные интерфейсы и создает прокси-объекты для методов, помеченных @Query.
Выполнение:
Когда метод репозитория вызывается, Spring Data JPA выполняет запрос, указанный в @Query. Если запрос JPQL, он преобразуется в SQL с помощью JPA-провайдера (например, Hibernate). Если запрос нативный, он выполняется напрямую.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации запросов.
Механизмы Spring, связанные с @Query
Spring Data JPA:
Spring Data JPA предоставляет реализацию репозиториев, которая автоматически обрабатывает аннотацию @Query. Она интегрируется с JPA-провайдером (например, Hibernate) для выполнения запросов.
JPA-провайдер:
JPA-провайдер (например, Hibernate) отвечает за преобразование JPQL-запросов в SQL и их выполнение. Для нативных запросов JPA-провайдер передает SQL напрямую в базу данных.
Транзакционность:
По умолчанию методы репозитория выполняются в транзакции. Это можно настроить с помощью аннотации @Transactional.
Варианты настройки
Использование именованных запросов:
Вместо указания запроса непосредственно в @Query, можно использовать именованные запросы, определенные в orm.xml или через @NamedQuery.
Пагинация и сортировка:
Методы с @Query могут поддерживать пагинацию и сортировку, если возвращают Page, Slice или List с параметром Pageable.
Проекции:
Можно использовать проекции DTO для возврата только необходимых полей:
@Query("SELECT new com.example.UserDTO(u.id, u.name) FROM User u WHERE u.email = ?1")
UserDTO findUserDtoByEmail(String email);
Динамические запросы:
Для сложных запросов можно использовать JpaSpecificationExecutor или Querydsl.
#Java #Training #Hard #Spring #SpringDataJPA #Query
Аннотация @Modifying
Аннотация @Modifying используется в Spring Data JPA для указания того, что метод репозитория выполняет модифицирующие операции (например, UPDATE, DELETE, INSERT) в базе данных. Она применяется в сочетании с аннотацией @Query и находится в пакете org.springframework.data.jpa.repository.
Параметры аннотации
flushAutomatically (необязательный):
Тип: boolean.
Значение по умолчанию: false.
Описание: Если установлено в true, то перед выполнением запроса будет выполнен сброс (flush) контекста (Persistence Context). Это гарантирует, что все ожидающие изменения будут синхронизированы с базой данных перед выполнением модифицирующего запроса.
Пример:
clearAutomatically (необязательный):
Тип: boolean.
Значение по умолчанию: false.
Описание: Если установлено в true, то после выполнения запроса будет очищен (clear) контекст (Persistence Context). Это полезно, чтобы избежать использования устаревших данных из кэша первого уровня.
Пример:
Жизненный цикл аннотации
Инициализация:
Аннотация @Modifying обрабатывается во время инициализации Spring-контекста. Spring Data JPA анализирует методы репозитория, помеченные @Modifying, и настраивает их для выполнения модифицирующих операций.
Выполнение:
Когда метод репозитория вызывается, Spring Data JPA выполняет запрос, указанный в @Query, с учетом настроек @Modifying. Если flushAutomatically = true, выполняется сброс контекста перед запросом. Если clearAutomatically = true, контекст очищается после запроса.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации выполнения запросов.
Механизмы Spring, связанные с @Modifying
Spring Data JPA:
Spring Data JPA предоставляет реализацию репозиториев, которая автоматически обрабатывает аннотацию @Modifying. Она интегрируется с JPA-провайдером (например, Hibernate) для выполнения модифицирующих запросов.
JPA-провайдер:
JPA-провайдер (например, Hibernate) отвечает за выполнение модифицирующих запросов. Для операций UPDATE и DELETE JPA-провайдер использует механизм EntityManager.
Транзакционность:
Методы, помеченные @Modifying, должны выполняться в транзакции. Если транзакция не настроена, Spring Data JPA выбросит исключение. Транзакционность можно настроить с помощью аннотации @Transactional.
Spring Boot автоматически настраивает менеджер транзакций (PlatformTransactionManager). Для методов с @Modifying рекомендуется явно указать транзакционность:
Варианты настройки
Использование flushAutomatically:
Установка flushAutomatically = true полезна, если в контексте есть изменения, которые должны быть синхронизированы с базой данных перед выполнением модифицирующего запроса.
Использование clearAutomatically:
Установка clearAutomatically = true полезна, если после выполнения модифицирующего запроса необходимо избежать использования устаревших данных из кэша первого уровня.
Комбинирование с @Query:
Аннотация @Modifying всегда используется вместе с @Query. Например:
Использование @Transactional:
Методы с @Modifying должны быть помечены аннотацией @Transactional, чтобы гарантировать атомарность операций.
#Java #Training #Hard #Spring #SpringDataJPA #Modifying
Аннотация @Modifying используется в Spring Data JPA для указания того, что метод репозитория выполняет модифицирующие операции (например, UPDATE, DELETE, INSERT) в базе данных. Она применяется в сочетании с аннотацией @Query и находится в пакете org.springframework.data.jpa.repository.
Параметры аннотации
flushAutomatically (необязательный):
Тип: boolean.
Значение по умолчанию: false.
Описание: Если установлено в true, то перед выполнением запроса будет выполнен сброс (flush) контекста (Persistence Context). Это гарантирует, что все ожидающие изменения будут синхронизированы с базой данных перед выполнением модифицирующего запроса.
Пример:
@Modifying(flushAutomatically = true)
@Query("UPDATE User u SET u.active = false WHERE u.lastLogin < :date")
void deactivateUsers(@Param("date") LocalDate date);
clearAutomatically (необязательный):
Тип: boolean.
Значение по умолчанию: false.
Описание: Если установлено в true, то после выполнения запроса будет очищен (clear) контекст (Persistence Context). Это полезно, чтобы избежать использования устаревших данных из кэша первого уровня.
Пример:
@Modifying(clearAutomatically = true)
@Query("DELETE FROM User u WHERE u.active = false")
void deleteInactiveUsers();
Жизненный цикл аннотации
Инициализация:
Аннотация @Modifying обрабатывается во время инициализации Spring-контекста. Spring Data JPA анализирует методы репозитория, помеченные @Modifying, и настраивает их для выполнения модифицирующих операций.
Выполнение:
Когда метод репозитория вызывается, Spring Data JPA выполняет запрос, указанный в @Query, с учетом настроек @Modifying. Если flushAutomatically = true, выполняется сброс контекста перед запросом. Если clearAutomatically = true, контекст очищается после запроса.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации выполнения запросов.
Механизмы Spring, связанные с @Modifying
Spring Data JPA:
Spring Data JPA предоставляет реализацию репозиториев, которая автоматически обрабатывает аннотацию @Modifying. Она интегрируется с JPA-провайдером (например, Hibernate) для выполнения модифицирующих запросов.
JPA-провайдер:
JPA-провайдер (например, Hibernate) отвечает за выполнение модифицирующих запросов. Для операций UPDATE и DELETE JPA-провайдер использует механизм EntityManager.
Транзакционность:
Методы, помеченные @Modifying, должны выполняться в транзакции. Если транзакция не настроена, Spring Data JPA выбросит исключение. Транзакционность можно настроить с помощью аннотации @Transactional.
Spring Boot автоматически настраивает менеджер транзакций (PlatformTransactionManager). Для методов с @Modifying рекомендуется явно указать транзакционность:
@Transactional
@Modifying
@Query("UPDATE User u SET u.active = false WHERE u.lastLogin < :date")
void deactivateUsers(@Param("date") LocalDate date);
Варианты настройки
Использование flushAutomatically:
Установка flushAutomatically = true полезна, если в контексте есть изменения, которые должны быть синхронизированы с базой данных перед выполнением модифицирующего запроса.
Использование clearAutomatically:
Установка clearAutomatically = true полезна, если после выполнения модифицирующего запроса необходимо избежать использования устаревших данных из кэша первого уровня.
Комбинирование с @Query:
Аннотация @Modifying всегда используется вместе с @Query. Например:
Использование @Transactional:
Методы с @Modifying должны быть помечены аннотацией @Transactional, чтобы гарантировать атомарность операций.
#Java #Training #Hard #Spring #SpringDataJPA #Modifying
Аннотация @Param
Аннотация @Param используется в Spring Data JPA для привязки параметров метода к именованным параметрам в JPQL или нативных SQL-запросах. Она позволяет явно указать, какие аргументы метода должны быть переданы в запрос. Аннотация находится в пакете org.springframework.data.repository.query.
Параметры аннотации
value (обязательный):
Тип: String.
Описание: Указывает имя параметра, которое будет использоваться в запросе. Это имя должно совпадать с именем параметра в запросе, указанном в @Query.
Пример:
Жизненный цикл аннотации
Инициализация:
Аннотация @Param обрабатывается во время инициализации Spring-контекста. Spring Data JPA анализирует методы репозитория и связывает параметры метода с именованными параметрами в запросе.
Выполнение:
Когда метод репозитория вызывается, Spring Data JPA подставляет значения параметров метода в запрос, используя имена, указанные в @Param.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для привязки параметров.
Варианты настройки
Использование в JPQL:
Аннотация @Param используется для привязки параметров в JPQL-запросах:
Использование в нативных SQL-запросах:
Аннотация @Param также может использоваться в нативных SQL-запросах:
Использование с @Modifying:
Аннотация @Param может использоваться в методах, помеченных @Modifying, для выполнения модифицирующих операций:
#Java #Training #Hard #Spring #SpringDataJPA #Param
Аннотация @Param используется в Spring Data JPA для привязки параметров метода к именованным параметрам в JPQL или нативных SQL-запросах. Она позволяет явно указать, какие аргументы метода должны быть переданы в запрос. Аннотация находится в пакете org.springframework.data.repository.query.
Параметры аннотации
value (обязательный):
Тип: String.
Описание: Указывает имя параметра, которое будет использоваться в запросе. Это имя должно совпадать с именем параметра в запросе, указанном в @Query.
Пример:
@Query("SELECT u FROM User u WHERE u.email = :email")
User findByEmail(@Param("email") String email);
Жизненный цикл аннотации
Инициализация:
Аннотация @Param обрабатывается во время инициализации Spring-контекста. Spring Data JPA анализирует методы репозитория и связывает параметры метода с именованными параметрами в запросе.
Выполнение:
Когда метод репозитория вызывается, Spring Data JPA подставляет значения параметров метода в запрос, используя имена, указанные в @Param.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для привязки параметров.
Варианты настройки
Использование в JPQL:
Аннотация @Param используется для привязки параметров в JPQL-запросах:
@Query("SELECT u FROM User u WHERE u.email = :email AND u.age > :age")
User findByEmailAndAge(@Param("email") String email, @Param("age") int age);
Использование в нативных SQL-запросах:
Аннотация @Param также может использоваться в нативных SQL-запросах:
@Query(value = "SELECT * FROM users WHERE email = :email", nativeQuery = true)
User findByEmail(@Param("email") String email);
Использование с @Modifying:
Аннотация @Param может использоваться в методах, помеченных @Modifying, для выполнения модифицирующих операций:
@Modifying
@Query("UPDATE User u SET u.active = :active WHERE u.email = :email")
void updateUserStatus(@Param("email") String email, @Param("active") boolean active);
#Java #Training #Hard #Spring #SpringDataJPA #Param
Аннотация @Transactional
Аннотация @Transactional используется в Spring для управления транзакциями на уровне методов или классов. Она позволяет декларативно определять границы транзакций, их поведение и настройки. Аннотация находится в пакете org.springframework.transaction.annotation.
Параметры аннотации
value (необязательный):
Тип: String.
Значение по умолчанию: "".
Описание: Указывает имя менеджера транзакций (бина PlatformTransactionManager), который должен использоваться для управления транзакцией. Если не указано, используется менеджер транзакций по умолчанию.
Пример:
propagation (необязательный):
Тип: Propagation.
Значение по умолчанию: Propagation.REQUIRED.
Описание: Определяет поведение распространения транзакции.
Возможные значения:
REQUIRED: Использует текущую транзакцию, если она существует, или создает новую.
REQUIRES_NEW: Всегда создает новую транзакцию, приостанавливая текущую, если она существует.
SUPPORTS: Использует текущую транзакцию, если она существует, но не создает новую.
NOT_SUPPORTED: Выполняет метод вне транзакции, приостанавливая текущую, если она существует.
MANDATORY: Требует наличия активной транзакции, иначе выбрасывает исключение.
NEVER: Запрещает выполнение метода в транзакции, иначе выбрасывает исключение.
NESTED: Создает вложенную транзакцию, если текущая транзакция существует.
Пример:
isolation (необязательный):
Тип: Isolation.
Значение по умолчанию: Isolation.DEFAULT.
Описание: Определяет уровень изоляции транзакции.
Возможные значения:
DEFAULT: Использует уровень изоляции по умолчанию для базы данных.
READ_UNCOMMITTED: Позволяет читать незафиксированные изменения других транзакций.
READ_COMMITTED: Гарантирует, что читаются только зафиксированные данные.
REPEATABLE_READ: Гарантирует, что данные, прочитанные в транзакции, не изменятся другими транзакциями.
SERIALIZABLE: Самый строгий уровень изоляции, предотвращает любые конфликты.
Пример:
timeout (необязательный):
Тип: int.
Значение по умолчанию: -1 (без тайм-аута).
Описание: Указывает максимальное время выполнения транзакции в секундах. Если время превышено, транзакция откатывается.
Пример:
readOnly (необязательный)
Тип: boolean.
Значение по умолчанию: false.
Описание: Указывает, является ли транзакция только для чтения. Если true, это может оптимизировать выполнение запросов.
Пример:
rollbackFor (необязательный):
Тип: Class<? extends Throwable>[].
Значение по умолчанию: {}.
Описание: Указывает типы исключений, при которых транзакция должна быть откачена. По умолчанию откат происходит только для непроверяемых исключений (RuntimeException и его подклассов).
Пример:
noRollbackFor (необязательный):
Тип: Class<? extends Throwable>[].
Значение по умолчанию: {}.
Описание: Указывает типы исключений, при которых транзакция не должна быть откачена.
Пример:
#Java #Training #Hard #Spring #SpringDataJPA #Transactional
Аннотация @Transactional используется в Spring для управления транзакциями на уровне методов или классов. Она позволяет декларативно определять границы транзакций, их поведение и настройки. Аннотация находится в пакете org.springframework.transaction.annotation.
Параметры аннотации
value (необязательный):
Тип: String.
Значение по умолчанию: "".
Описание: Указывает имя менеджера транзакций (бина PlatformTransactionManager), который должен использоваться для управления транзакцией. Если не указано, используется менеджер транзакций по умолчанию.
Пример:
@Transactional("customTransactionManager")
public void performOperation() {
// Логика метода
}
propagation (необязательный):
Тип: Propagation.
Значение по умолчанию: Propagation.REQUIRED.
Описание: Определяет поведение распространения транзакции.
Возможные значения:
REQUIRED: Использует текущую транзакцию, если она существует, или создает новую.
REQUIRES_NEW: Всегда создает новую транзакцию, приостанавливая текущую, если она существует.
SUPPORTS: Использует текущую транзакцию, если она существует, но не создает новую.
NOT_SUPPORTED: Выполняет метод вне транзакции, приостанавливая текущую, если она существует.
MANDATORY: Требует наличия активной транзакции, иначе выбрасывает исключение.
NEVER: Запрещает выполнение метода в транзакции, иначе выбрасывает исключение.
NESTED: Создает вложенную транзакцию, если текущая транзакция существует.
Пример:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void performOperation() {
// Логика метода
}
isolation (необязательный):
Тип: Isolation.
Значение по умолчанию: Isolation.DEFAULT.
Описание: Определяет уровень изоляции транзакции.
Возможные значения:
DEFAULT: Использует уровень изоляции по умолчанию для базы данных.
READ_UNCOMMITTED: Позволяет читать незафиксированные изменения других транзакций.
READ_COMMITTED: Гарантирует, что читаются только зафиксированные данные.
REPEATABLE_READ: Гарантирует, что данные, прочитанные в транзакции, не изменятся другими транзакциями.
SERIALIZABLE: Самый строгий уровень изоляции, предотвращает любые конфликты.
Пример:
@Transactional(isolation = Isolation.READ_COMMITTED)
public void performOperation() {
// Логика метода
}
timeout (необязательный):
Тип: int.
Значение по умолчанию: -1 (без тайм-аута).
Описание: Указывает максимальное время выполнения транзакции в секундах. Если время превышено, транзакция откатывается.
Пример:
@Transactional(timeout = 10)
public void performOperation() {
// Логика метода
}
readOnly (необязательный)
Тип: boolean.
Значение по умолчанию: false.
Описание: Указывает, является ли транзакция только для чтения. Если true, это может оптимизировать выполнение запросов.
Пример:
@Transactional(readOnly = true)
public void readData() {
// Логика метода
}
rollbackFor (необязательный):
Тип: Class<? extends Throwable>[].
Значение по умолчанию: {}.
Описание: Указывает типы исключений, при которых транзакция должна быть откачена. По умолчанию откат происходит только для непроверяемых исключений (RuntimeException и его подклассов).
Пример:
@Transactional(rollbackFor = {CustomException.class})
public void performOperation() throws CustomException {
// Логика метода
}
noRollbackFor (необязательный):
Тип: Class<? extends Throwable>[].
Значение по умолчанию: {}.
Описание: Указывает типы исключений, при которых транзакция не должна быть откачена.
Пример:
@Transactional(noRollbackFor = {CustomException.class})
public void performOperation() throws CustomException {
// Логика метода
}
#Java #Training #Hard #Spring #SpringDataJPA #Transactional
Жизненный цикл аннотации
Инициализация:
Аннотация @Transactional обрабатывается во время инициализации Spring-контекста. Spring создает прокси-объекты для методов или классов, помеченных @Transactional.
Выполнение:
Когда метод вызывается, Spring проверяет настройки транзакции и начинает новую транзакцию (или использует существующую) в соответствии с параметрами propagation.
Если метод завершается успешно, транзакция фиксируется (commit). Если возникает исключение, транзакция откатывается (rollback), если это указано в параметрах.
Уничтожение:
После завершения метода транзакция завершается (фиксируется или откатывается), и ресурсы освобождаются.
Механизмы Spring и настройки Spring Boot
Spring AOP (Aspect-Oriented Programming):
Spring использует AOP для создания прокси-объектов, которые перехватывают вызовы методов, помеченных @Transactional, и управляют транзакциями.
PlatformTransactionManager:
Spring предоставляет интерфейс PlatformTransactionManager для управления транзакциями. Реализации включают DataSourceTransactionManager (для JDBC) и JpaTransactionManager (для JPA).
TransactionTemplate:
Для программного управления транзакциями можно использовать TransactionTemplate.
Варианты настройки
Использование нескольких менеджеров транзакций:
Если в приложении используется несколько источников данных, можно настроить несколько менеджеров транзакций и указывать их в параметре value аннотации @Transactional.
Программное управление транзакциями:
Для сложных сценариев можно использовать TransactionTemplate:
Использование вложенных транзакций:
Уровень изоляции NESTED позволяет создавать вложенные транзакции, которые могут быть откачены независимо от основной транзакции.
#Java #Training #Hard #Spring #SpringDataJPA #Transactional
Инициализация:
Аннотация @Transactional обрабатывается во время инициализации Spring-контекста. Spring создает прокси-объекты для методов или классов, помеченных @Transactional.
Выполнение:
Когда метод вызывается, Spring проверяет настройки транзакции и начинает новую транзакцию (или использует существующую) в соответствии с параметрами propagation.
Если метод завершается успешно, транзакция фиксируется (commit). Если возникает исключение, транзакция откатывается (rollback), если это указано в параметрах.
Уничтожение:
После завершения метода транзакция завершается (фиксируется или откатывается), и ресурсы освобождаются.
Механизмы Spring и настройки Spring Boot
Spring AOP (Aspect-Oriented Programming):
Spring использует AOP для создания прокси-объектов, которые перехватывают вызовы методов, помеченных @Transactional, и управляют транзакциями.
PlatformTransactionManager:
Spring предоставляет интерфейс PlatformTransactionManager для управления транзакциями. Реализации включают DataSourceTransactionManager (для JDBC) и JpaTransactionManager (для JPA).
TransactionTemplate:
Для программного управления транзакциями можно использовать TransactionTemplate.
Варианты настройки
Использование нескольких менеджеров транзакций:
Если в приложении используется несколько источников данных, можно настроить несколько менеджеров транзакций и указывать их в параметре value аннотации @Transactional.
Программное управление транзакциями:
Для сложных сценариев можно использовать TransactionTemplate:
@Autowired
private TransactionTemplate transactionTemplate;
public void performOperation() {
transactionTemplate.execute(status -> {
// Логика метода
return null;
});
}
Использование вложенных транзакций:
Уровень изоляции NESTED позволяет создавать вложенные транзакции, которые могут быть откачены независимо от основной транзакции.
#Java #Training #Hard #Spring #SpringDataJPA #Transactional
Аннотация @EnableJpaRepositories
Аннотация @EnableJpaRepositories используется в Spring Data JPA для активации репозиториев JPA в приложении. Она сканирует пакеты и регистрирует интерфейсы, расширяющие JpaRepository, как бины Spring. Аннотация находится в пакете org.springframework.data.jpa.repository.config.
Параметры аннотации
basePackages (необязательный):
Тип: String[].
Значение по умолчанию: {}.
Описание: Указывает пакеты, которые должны быть сканированы для поиска репозиториев JPA. Если не указано, используется пакет, в котором находится класс с аннотацией.
Пример:
basePackageClasses (необязательный):
Тип: Class<?>[].
Значение по умолчанию: {}.
Описание: Указывает классы, пакеты которых должны быть сканированы для поиска репозиториев JPA. Это альтернатива basePackages.
Пример:
includeFilters (необязательный):
Тип: ComponentScan.Filter[].
Значение по умолчанию: {}.
Описание: Указывает фильтры для включения определенных классов в сканирование репозиториев.
Пример:
excludeFilters (необязательный):
Тип: ComponentScan.Filter[].
Значение по умолчанию: {}.
Описание: Указывает фильтры для исключения определенных классов из сканирования репозиториев.
Пример:
repositoryImplementationPostfix (необязательный):
Тип: String.
Значение по умолчанию: "Impl".
Описание: Указывает постфикс для классов реализации репозиториев.
Пример:
entityManagerFactoryRef (необязательный):
Тип: String.
Значение по умолчанию: "entityManagerFactory".
Описание: Указывает имя бина EntityManagerFactory, который должен использоваться для репозиториев.
Пример:
transactionManagerRef (необязательный):
Тип: String.
Значение по умолчанию: "transactionManager".
Описание: Указывает имя бина PlatformTransactionManager, который должен использоваться для управления транзакциями репозиториев.
Пример:
considerNestedRepositories (необязательный):
Тип: boolean.
Значение по умолчанию: false.
Описание: Указывает, должны ли сканироваться вложенные репозитории (например, внутри других классов).
Пример:
enableDefaultTransactions (необязательный):
Тип: boolean.
Значение по умолчанию: true.
Описание: Указывает, должны ли методы репозиториев выполняться в транзакции по умолчанию.
Пример:
Жизненный цикл аннотации
Инициализация:
Аннотация @EnableJpaRepositories обрабатывается во время инициализации Spring-контекста. Spring Data JPA сканирует указанные пакеты и регистрирует интерфейсы репозиториев как бины.
Выполнение:
Когда приложение запущено, Spring Data JPA создает прокси-объекты для интерфейсов репозиториев, которые реализуют методы, определенные в JpaRepository и пользовательских запросах.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации репозиториев.
#Java #Training #Hard #Spring #SpringDataJPA #EnableJpaRepositories
Аннотация @EnableJpaRepositories используется в Spring Data JPA для активации репозиториев JPA в приложении. Она сканирует пакеты и регистрирует интерфейсы, расширяющие JpaRepository, как бины Spring. Аннотация находится в пакете org.springframework.data.jpa.repository.config.
Параметры аннотации
basePackages (необязательный):
Тип: String[].
Значение по умолчанию: {}.
Описание: Указывает пакеты, которые должны быть сканированы для поиска репозиториев JPA. Если не указано, используется пакет, в котором находится класс с аннотацией.
Пример:
@EnableJpaRepositories(basePackages = "com.example.repositories")
basePackageClasses (необязательный):
Тип: Class<?>[].
Значение по умолчанию: {}.
Описание: Указывает классы, пакеты которых должны быть сканированы для поиска репозиториев JPA. Это альтернатива basePackages.
Пример:
@EnableJpaRepositories(basePackageClasses = {UserRepository.class, ProductRepository.class})
includeFilters (необязательный):
Тип: ComponentScan.Filter[].
Значение по умолчанию: {}.
Описание: Указывает фильтры для включения определенных классов в сканирование репозиториев.
Пример:
@EnableJpaRepositories(includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = CustomRepository.class))
excludeFilters (необязательный):
Тип: ComponentScan.Filter[].
Значение по умолчанию: {}.
Описание: Указывает фильтры для исключения определенных классов из сканирования репозиториев.
Пример:
@EnableJpaRepositories(excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = ExcludedRepository.class))
repositoryImplementationPostfix (необязательный):
Тип: String.
Значение по умолчанию: "Impl".
Описание: Указывает постфикс для классов реализации репозиториев.
Пример:
@EnableJpaRepositories(repositoryImplementationPostfix = "CustomImpl")
entityManagerFactoryRef (необязательный):
Тип: String.
Значение по умолчанию: "entityManagerFactory".
Описание: Указывает имя бина EntityManagerFactory, который должен использоваться для репозиториев.
Пример:
@EnableJpaRepositories(entityManagerFactoryRef = "customEntityManagerFactory")
transactionManagerRef (необязательный):
Тип: String.
Значение по умолчанию: "transactionManager".
Описание: Указывает имя бина PlatformTransactionManager, который должен использоваться для управления транзакциями репозиториев.
Пример:
@EnableJpaRepositories(transactionManagerRef = "customTransactionManager")
considerNestedRepositories (необязательный):
Тип: boolean.
Значение по умолчанию: false.
Описание: Указывает, должны ли сканироваться вложенные репозитории (например, внутри других классов).
Пример:
@EnableJpaRepositories(considerNestedRepositories = true)
enableDefaultTransactions (необязательный):
Тип: boolean.
Значение по умолчанию: true.
Описание: Указывает, должны ли методы репозиториев выполняться в транзакции по умолчанию.
Пример:
@EnableJpaRepositories(enableDefaultTransactions = false)
Жизненный цикл аннотации
Инициализация:
Аннотация @EnableJpaRepositories обрабатывается во время инициализации Spring-контекста. Spring Data JPA сканирует указанные пакеты и регистрирует интерфейсы репозиториев как бины.
Выполнение:
Когда приложение запущено, Spring Data JPA создает прокси-объекты для интерфейсов репозиториев, которые реализуют методы, определенные в JpaRepository и пользовательских запросах.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации репозиториев.
#Java #Training #Hard #Spring #SpringDataJPA #EnableJpaRepositories
Аннотация @EntityGraph
Аннотация @EntityGraph используется в Spring Data JPA для управления стратегией загрузки связанных сущностей (например, EAGER или LAZY). Она позволяет динамически определять, какие ассоциации должны быть загружены вместе с основной сущностью, что помогает избежать проблемы N+1 запросов. Аннотация находится в пакете org.springframework.data.jpa.repository.EntityGraph.
Параметры аннотации
value (необязательный):
Тип: String.
Значение по умолчанию: "".
Описание: Указывает имя именованного графа сущности (Named EntityGraph), который должен быть использован. Именованный граф должен быть определен в сущности с помощью аннотации @NamedEntityGraph.
Пример:
type (необязательный):
Тип: EntityGraphType.
Значение по умолчанию: EntityGraphType.FETCH.
Описание: Определяет тип графа сущности.
Возможные значения:
FETCH: Загружает только указанные ассоциации.
LOAD: Загружает указанные ассоциации, а остальные загружает в соответствии с их стратегией загрузки (например, LAZY или EAGER).
Пример:
attributePaths (необязательный):
Тип: String[].
Значение по умолчанию: {}.
Описание: Указывает пути к атрибутам сущности, которые должны быть загружены. Это альтернатива использованию именованного графа.
Пример:
Жизненный цикл аннотации
Инициализация:
Аннотация @EntityGraph обрабатывается во время инициализации Spring-контекста. Spring Data JPA анализирует методы репозитория и настраивает графы сущностей.
Выполнение:
Когда метод репозитория вызывается, Spring Data JPA применяет указанный граф сущности к запросу, загружая указанные ассоциации.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации загрузки сущностей.
Варианты настройки
Использование именованных графов:
Именованные графы сущностей можно определить в сущности с помощью аннотации @NamedEntityGraph:
Использование динамических графов:
Динамические графы можно указать с помощью параметра attributePaths:
Комбинирование с @Query:
Аннотация @EntityGraph может использоваться вместе с @Query для более сложных запросов:
Использование нескольких графов:
Можно указать несколько графов сущностей, если это поддерживается JPA-провайдером.
#Java #Training #Hard #Spring #SpringDataJPA #EntityGraph
Аннотация @EntityGraph используется в Spring Data JPA для управления стратегией загрузки связанных сущностей (например, EAGER или LAZY). Она позволяет динамически определять, какие ассоциации должны быть загружены вместе с основной сущностью, что помогает избежать проблемы N+1 запросов. Аннотация находится в пакете org.springframework.data.jpa.repository.EntityGraph.
Параметры аннотации
value (необязательный):
Тип: String.
Значение по умолчанию: "".
Описание: Указывает имя именованного графа сущности (Named EntityGraph), который должен быть использован. Именованный граф должен быть определен в сущности с помощью аннотации @NamedEntityGraph.
Пример:
@EntityGraph(value = "User.withAddress")
User findById(Long id);
type (необязательный):
Тип: EntityGraphType.
Значение по умолчанию: EntityGraphType.FETCH.
Описание: Определяет тип графа сущности.
Возможные значения:
FETCH: Загружает только указанные ассоциации.
LOAD: Загружает указанные ассоциации, а остальные загружает в соответствии с их стратегией загрузки (например, LAZY или EAGER).
Пример:
@EntityGraph(type = EntityGraphType.LOAD)
User findById(Long id);
attributePaths (необязательный):
Тип: String[].
Значение по умолчанию: {}.
Описание: Указывает пути к атрибутам сущности, которые должны быть загружены. Это альтернатива использованию именованного графа.
Пример:
@EntityGraph(attributePaths = {"address", "orders"})
User findById(Long id);
Жизненный цикл аннотации
Инициализация:
Аннотация @EntityGraph обрабатывается во время инициализации Spring-контекста. Spring Data JPA анализирует методы репозитория и настраивает графы сущностей.
Выполнение:
Когда метод репозитория вызывается, Spring Data JPA применяет указанный граф сущности к запросу, загружая указанные ассоциации.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации загрузки сущностей.
Варианты настройки
Использование именованных графов:
Именованные графы сущностей можно определить в сущности с помощью аннотации @NamedEntityGraph:
@Entity
@NamedEntityGraph(name = "User.withAddress", attributeNodes = @NamedAttributeNode("address"))
public class User {
// Поля и методы
}
Использование динамических графов:
Динамические графы можно указать с помощью параметра attributePaths:
@EntityGraph(attributePaths = {"address", "orders"})
User findById(Long id);
Комбинирование с @Query:
Аннотация @EntityGraph может использоваться вместе с @Query для более сложных запросов:
@EntityGraph(attributePaths = {"address"})
@Query("SELECT u FROM User u WHERE u.email = :email")
User findByEmail(@Param("email") String email);
Использование нескольких графов:
Можно указать несколько графов сущностей, если это поддерживается JPA-провайдером.
#Java #Training #Hard #Spring #SpringDataJPA #EntityGraph
Аннотация @Lock
Аннотация @Lock используется в Spring Data JPA для указания типа блокировки, которая должна быть применена при выполнении запроса. Это полезно для управления параллельным доступом к данным и предотвращения проблем, таких как потерянные обновления или грязное чтение. Аннотация находится в пакете org.springframework.data.jpa.repository.Lock.
Параметры аннотации
value (обязательный):
Тип: LockModeType.
Описание: Указывает тип блокировки, который должен быть применен к запросу.
Возможные значения:
LockModeType.PESSIMISTIC_READ: Пессимистическая блокировка для чтения. Позволяет другим транзакциям читать данные, но не изменять их.
LockModeType.PESSIMISTIC_WRITE: Пессимистическая блокировка для записи. Блокирует данные для чтения и записи другими транзакциями.
LockModeType.PESSIMISTIC_FORCE_INCREMENT: Пессимистическая блокировка с принудительным увеличением версии (используется с оптимистичной блокировкой).
LockModeType.OPTIMISTIC: Оптимистическая блокировка. Проверяет версию сущности при фиксации транзакции.
LockModeType.OPTIMISTIC_FORCE_INCREMENT: Оптимистическая блокировка с принудительным увеличением версии.
LockModeType.NONE: Отсутствие блокировки (по умолчанию).
Пример:
Жизненный цикл аннотации
Инициализация:
Аннотация @Lock обрабатывается во время инициализации Spring-контекста. Spring Data JPA анализирует методы репозитория и настраивает блокировки.
Выполнение:
Когда метод репозитория вызывается, Spring Data JPA применяет указанную блокировку к запросу. Блокировка сохраняется до завершения транзакции.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации блокировок.
Варианты настройки
Использование пессимистических блокировок:
Пессимистические блокировки полезны для предотвращения конфликтов при параллельном доступе к данным:
Использование оптимистических блокировок:
Оптимистические блокировки полезны для предотвращения конфликтов при обновлении данных:
Комбинирование с @Query:
Аннотация @Lock может использоваться вместе с @Query для более сложных запросов:
Использование с @Transactional:
Методы с @Lock должны выполняться в транзакции, чтобы блокировка сохранялась до завершения транзакции:
#Java #Training #Hard #Spring #SpringDataJPA #Lock
Аннотация @Lock используется в Spring Data JPA для указания типа блокировки, которая должна быть применена при выполнении запроса. Это полезно для управления параллельным доступом к данным и предотвращения проблем, таких как потерянные обновления или грязное чтение. Аннотация находится в пакете org.springframework.data.jpa.repository.Lock.
Параметры аннотации
value (обязательный):
Тип: LockModeType.
Описание: Указывает тип блокировки, который должен быть применен к запросу.
Возможные значения:
LockModeType.PESSIMISTIC_READ: Пессимистическая блокировка для чтения. Позволяет другим транзакциям читать данные, но не изменять их.
LockModeType.PESSIMISTIC_WRITE: Пессимистическая блокировка для записи. Блокирует данные для чтения и записи другими транзакциями.
LockModeType.PESSIMISTIC_FORCE_INCREMENT: Пессимистическая блокировка с принудительным увеличением версии (используется с оптимистичной блокировкой).
LockModeType.OPTIMISTIC: Оптимистическая блокировка. Проверяет версию сущности при фиксации транзакции.
LockModeType.OPTIMISTIC_FORCE_INCREMENT: Оптимистическая блокировка с принудительным увеличением версии.
LockModeType.NONE: Отсутствие блокировки (по умолчанию).
Пример:
@Lock(LockModeType.PESSIMISTIC_WRITE)
User findById(Long id);
Жизненный цикл аннотации
Инициализация:
Аннотация @Lock обрабатывается во время инициализации Spring-контекста. Spring Data JPA анализирует методы репозитория и настраивает блокировки.
Выполнение:
Когда метод репозитория вызывается, Spring Data JPA применяет указанную блокировку к запросу. Блокировка сохраняется до завершения транзакции.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации блокировок.
Варианты настройки
Использование пессимистических блокировок:
Пессимистические блокировки полезны для предотвращения конфликтов при параллельном доступе к данным:
@Lock(LockModeType.PESSIMISTIC_WRITE)
User findById(Long id);
Использование оптимистических блокировок:
Оптимистические блокировки полезны для предотвращения конфликтов при обновлении данных:
@Lock(LockModeType.OPTIMISTIC)
User findById(Long id);
Комбинирование с @Query:
Аннотация @Lock может использоваться вместе с @Query для более сложных запросов:
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("SELECT u FROM User u WHERE u.email = :email")
User findByEmail(@Param("email") String email);
Использование с @Transactional:
Методы с @Lock должны выполняться в транзакции, чтобы блокировка сохранялась до завершения транзакции:
@Transactional
@Lock(LockModeType.PESSIMISTIC_WRITE)
User findById(Long id);
#Java #Training #Hard #Spring #SpringDataJPA #Lock
Аннотация @Procedure
Аннотация @Procedure используется в Spring Data JPA для вызова хранимых процедур и функций, определенных в базе данных. Она позволяет интегрировать вызовы хранимых процедур в репозиторные интерфейсы Spring Data. Аннотация находится в пакете org.springframework.data.jpa.repository.query.
Параметры аннотации
value (необязательный):
Тип: String.
Значение по умолчанию: "".
Описание: Указывает имя хранимой процедуры или функции в базе данных. Если не указано, используется имя метода.
Пример:
procedureName (необязательный):
Тип: String.
Значение по умолчанию: "".
Описание: Альтернативное имя для параметра value. Указывает имя хранимой процедуры или функции.
Пример:
outputParameterName (необязательный):
Тип: String.
Значение по умолчанию: "".
Описание: Указывает имя выходного параметра, если хранимая процедура возвращает значение через выходной параметр.
Пример:
Жизненный цикл аннотации
Инициализация:
Аннотация @Procedure обрабатывается во время инициализации Spring-контекста. Spring Data JPA анализирует методы репозитория и настраивает вызовы хранимых процедур.
Выполнение:
Когда метод репозитория вызывается, Spring Data JPA выполняет указанную хранимую процедуру или функцию через JPA-провайдер (например, Hibernate).
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации вызовов хранимых процедур.
Варианты настройки
Использование именованных хранимых процедур:
Именованные хранимые процедуры можно определить в сущности с помощью аннотации @NamedStoredProcedureQuery:
Использование выходных параметров:
Если хранимая процедура возвращает значение через выходной параметр, можно указать его имя с помощью параметра outputParameterName:
Использование с @Query:
Аннотация @Procedure может использоваться вместе с @Query для более сложных сценариев:
Использование с @Transactional:
Методы с @Procedure должны выполняться в транзакции, чтобы гарантировать атомарность операций:
#Java #Training #Hard #Spring #SpringDataJPA #Procedure
Аннотация @Procedure используется в Spring Data JPA для вызова хранимых процедур и функций, определенных в базе данных. Она позволяет интегрировать вызовы хранимых процедур в репозиторные интерфейсы Spring Data. Аннотация находится в пакете org.springframework.data.jpa.repository.query.
Параметры аннотации
value (необязательный):
Тип: String.
Значение по умолчанию: "".
Описание: Указывает имя хранимой процедуры или функции в базе данных. Если не указано, используется имя метода.
Пример:
@Procedure("calculate_discount")
BigDecimal calculateDiscount(@Param("orderId") Long orderId);
procedureName (необязательный):
Тип: String.
Значение по умолчанию: "".
Описание: Альтернативное имя для параметра value. Указывает имя хранимой процедуры или функции.
Пример:
@Procedure(procedureName = "calculate_discount")
BigDecimal calculateDiscount(@Param("orderId") Long orderId);
outputParameterName (необязательный):
Тип: String.
Значение по умолчанию: "".
Описание: Указывает имя выходного параметра, если хранимая процедура возвращает значение через выходной параметр.
Пример:
@Procedure(outputParameterName = "discount")
BigDecimal calculateDiscount(@Param("orderId") Long orderId);
Жизненный цикл аннотации
Инициализация:
Аннотация @Procedure обрабатывается во время инициализации Spring-контекста. Spring Data JPA анализирует методы репозитория и настраивает вызовы хранимых процедур.
Выполнение:
Когда метод репозитория вызывается, Spring Data JPA выполняет указанную хранимую процедуру или функцию через JPA-провайдер (например, Hibernate).
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации вызовов хранимых процедур.
Варианты настройки
Использование именованных хранимых процедур:
Именованные хранимые процедуры можно определить в сущности с помощью аннотации @NamedStoredProcedureQuery:
@Entity
@NamedStoredProcedureQuery(
name = "calculate_discount",
procedureName = "calculate_discount",
parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, name = "orderId", type = Long.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "discount", type = BigDecimal.class)
}
)
public class Order {
// Поля и методы
}
Использование выходных параметров:
Если хранимая процедура возвращает значение через выходной параметр, можно указать его имя с помощью параметра outputParameterName:
@Procedure(outputParameterName = "discount")
BigDecimal calculateDiscount(@Param("orderId") Long orderId);
Использование с @Query:
Аннотация @Procedure может использоваться вместе с @Query для более сложных сценариев:
@Procedure
@Query(value = "CALL calculate_discount(:orderId, :discount)", nativeQuery = true)
BigDecimal calculateDiscount(@Param("orderId") Long orderId, @Param("discount") BigDecimal discount);
Использование с @Transactional:
Методы с @Procedure должны выполняться в транзакции, чтобы гарантировать атомарность операций:
@Transactional
@Procedure("calculate_discount")
BigDecimal calculateDiscount(@Param("orderId") Long orderId);
#Java #Training #Hard #Spring #SpringDataJPA #Procedure
Аннотация @IdClass
Аннотация @IdClass используется в JPA (Java Persistence API) для указания класса, который представляет составной первичный ключ сущности. Она применяется, когда сущность имеет несколько полей, которые вместе образуют уникальный идентификатор (составной ключ). Аннотация находится в пакете javax.persistence.
Параметры аннотации
value (обязательный):
Тип: Class<?>.
Описание: Указывает класс, который представляет составной первичный ключ. Этот класс должен быть сериализуемым, иметь конструктор по умолчанию и переопределять методы equals() и hashCode().
Пример:
Жизненный цикл аннотации
Инициализация:
Аннотация @IdClass обрабатывается во время инициализации JPA-провайдера (например, Hibernate). JPA-провайдер анализирует сущность и создает метаданные для составного ключа.
Выполнение:
Когда сущность сохраняется, обновляется или извлекается из базы данных, JPA-провайдер использует класс, указанный в @IdClass, для работы с составным ключом.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации составного ключа.
Варианты настройки
Использование составного ключа:
Класс, представляющий составной ключ, должен быть сериализуемым, иметь конструктор по умолчанию и переопределять методы equals() и hashCode():
Использование с @Embeddable:
Вместо @IdClass можно использовать аннотацию @Embeddable для определения составного ключа:
Использование с репозиториями:
Репозитории Spring Data JPA могут работать с сущностями, имеющими составные ключи:
#Java #Training #Hard #Spring #SpringDataJPA #IdClass
Аннотация @IdClass используется в JPA (Java Persistence API) для указания класса, который представляет составной первичный ключ сущности. Она применяется, когда сущность имеет несколько полей, которые вместе образуют уникальный идентификатор (составной ключ). Аннотация находится в пакете javax.persistence.
Параметры аннотации
value (обязательный):
Тип: Class<?>.
Описание: Указывает класс, который представляет составной первичный ключ. Этот класс должен быть сериализуемым, иметь конструктор по умолчанию и переопределять методы equals() и hashCode().
Пример:
@IdClass(UserId.class)
public class User {
@Id
private Long departmentId;
@Id
private Long userId;
// Остальные поля и методы
}
Жизненный цикл аннотации
Инициализация:
Аннотация @IdClass обрабатывается во время инициализации JPA-провайдера (например, Hibernate). JPA-провайдер анализирует сущность и создает метаданные для составного ключа.
Выполнение:
Когда сущность сохраняется, обновляется или извлекается из базы данных, JPA-провайдер использует класс, указанный в @IdClass, для работы с составным ключом.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации составного ключа.
Варианты настройки
Использование составного ключа:
Класс, представляющий составной ключ, должен быть сериализуемым, иметь конструктор по умолчанию и переопределять методы equals() и hashCode():
public class UserId implements Serializable {
private Long departmentId;
private Long userId;
// Конструктор по умолчанию
public UserId() {}
// Конструктор с параметрами
public UserId(Long departmentId, Long userId) {
this.departmentId = departmentId;
this.userId = userId;
}
// Геттеры и сеттеры
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserId userId1 = (UserId) o;
return Objects.equals(departmentId, userId1.departmentId) &&
Objects.equals(userId, userId1.userId);
}
@Override
public int hashCode() {
return Objects.hash(departmentId, userId);
}
}
Использование с @Embeddable:
Вместо @IdClass можно использовать аннотацию @Embeddable для определения составного ключа:
@Embeddable
public class UserId implements Serializable {
private Long departmentId;
private Long userId;
// Конструктор по умолчанию, геттеры, сеттеры, equals, hashCode
}
@Entity
public class User {
@EmbeddedId
private UserId id;
// Остальные поля и методы
}
Использование с репозиториями:
Репозитории Spring Data JPA могут работать с сущностями, имеющими составные ключи:
public interface UserRepository extends JpaRepository<User, UserId> {
// Методы репозитория
}
#Java #Training #Hard #Spring #SpringDataJPA #IdClass
Аннотация @MapsId
Аннотация @MapsId используется в JPA (Java Persistence API) для указания, что внешний ключ сущности также является её первичным ключом. Это полезно при работе с отношениями "один к одному" или "многие к одному", где дочерняя сущность использует первичный ключ родительской сущности в качестве своего собственного первичного ключа. Аннотация находится в пакете javax.persistence.
Параметры аннотации
value (необязательный):
Тип: String.
Значение по умолчанию: "".
Описание: Указывает имя атрибута сущности, который является первичным ключом. Если не указано, используется первичный ключ родительской сущности.
Пример:
Жизненный цикл аннотации
Инициализация:
Аннотация @MapsId обрабатывается во время инициализации JPA-провайдера (например, Hibernate). JPA-провайдер анализирует сущность и создает метаданные для связи с родительской сущностью.
Выполнение:
Когда сущность сохраняется, обновляется или извлекается из базы данных, JPA-провайдер использует первичный ключ родительской сущности в качестве первичного ключа дочерней сущности.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации связи с родительской сущностью.
Варианты настройки
Использование с @OneToOne:
Аннотация @MapsId часто используется с отношением "один к одному":
Использование с @ManyToOne:
Аннотация @MapsId также может использоваться с отношением "многие к одному":
Использование с составными ключами:
Аннотация @MapsId может использоваться с составными ключами, если родительская сущность имеет составной ключ:
Использование с репозиториями:
Репозитории Spring Data JPA могут работать с сущностями, имеющими аннотацию @MapsId:
#Java #Training #Hard #Spring #SpringDataJPA #MapsId
Аннотация @MapsId используется в JPA (Java Persistence API) для указания, что внешний ключ сущности также является её первичным ключом. Это полезно при работе с отношениями "один к одному" или "многие к одному", где дочерняя сущность использует первичный ключ родительской сущности в качестве своего собственного первичного ключа. Аннотация находится в пакете javax.persistence.
Параметры аннотации
value (необязательный):
Тип: String.
Значение по умолчанию: "".
Описание: Указывает имя атрибута сущности, который является первичным ключом. Если не указано, используется первичный ключ родительской сущности.
Пример:
@MapsId("userId")
@OneToOne
@JoinColumn(name = "user_id")
private User user;
Жизненный цикл аннотации
Инициализация:
Аннотация @MapsId обрабатывается во время инициализации JPA-провайдера (например, Hibernate). JPA-провайдер анализирует сущность и создает метаданные для связи с родительской сущностью.
Выполнение:
Когда сущность сохраняется, обновляется или извлекается из базы данных, JPA-провайдер использует первичный ключ родительской сущности в качестве первичного ключа дочерней сущности.
Уничтожение:
Аннотация не имеет явного жизненного цикла уничтожения, так как она используется только для конфигурации связи с родительской сущностью.
Варианты настройки
Использование с @OneToOne:
Аннотация @MapsId часто используется с отношением "один к одному":
@Entity
public class UserProfile {
@Id
private Long userId;
@MapsId
@OneToOne
@JoinColumn(name = "user_id")
private User user;
// Остальные поля и методы
}
Использование с @ManyToOne:
Аннотация @MapsId также может использоваться с отношением "многие к одному":
@Entity
public class Order {
@Id
private Long orderId;
@MapsId("userId")
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
// Остальные поля и методы
}
Использование с составными ключами:
Аннотация @MapsId может использоваться с составными ключами, если родительская сущность имеет составной ключ:
@Entity
public class UserProfile {
@EmbeddedId
private UserProfileId id;
@MapsId("userId")
@ManyToOne
@JoinColumns({
@JoinColumn(name = "department_id", referencedColumnName = "departmentId"),
@JoinColumn(name = "user_id", referencedColumnName = "userId")
})
private User user;
// Остальные поля и методы
}
Использование с репозиториями:
Репозитории Spring Data JPA могут работать с сущностями, имеющими аннотацию @MapsId:
public interface UserProfileRepository extends JpaRepository<UserProfile, Long> {
// Методы репозитория
}
#Java #Training #Hard #Spring #SpringDataJPA #MapsId
Аннотация @CreatedBy
Аннотация @CreatedBy используется в Spring Data для автоматического заполнения поля информацией о пользователе, создавшем сущность. Это часть механизма аудита Spring Data, позволяющего автоматически отслеживать, кто и когда создавал или изменял сущности. Аннотация находится в пакете org.springframework.data.annotation.
Параметры аннотации
Аннотация @CreatedBy не имеет параметров. Она применяется к полям сущности, которые должны автоматически заполняться информацией о создателе.
Пример использования:
Жизненный цикл аннотации
Инициализация:
Аннотация активируется при включении аудита через @EnableJpaAuditing
Требуется регистрация AuditingEntityListener для сущности
Выполнение:
Перед сохранением новой сущности (при вызове save())
Spring автоматически определяет текущего пользователя и устанавливает значение поля
Обновление:
Поле заполняется только при создании сущности
Не изменяется при последующих обновлениях
Механизмы Spring и настройки Spring Boot
AuditingEntityListener:
Класс, обрабатывающий события жизненного цикла сущности
Автоматически заполняет аннотированные поля
AuditorAware:
Интерфейс для получения информации о текущем пользователе
Требуется реализация для работы @CreatedBy
EnableJpaAuditing:
Аннотация для активации механизма аудита
Настройки Spring Boot
Активация аудита:
Конфигурация сущности:
Настройки безопасности (если используется Spring Security):
Варианты настройки
Типы полей:
Может использоваться с любым типом (String, Long, UUID)
Чаще всего используется String для хранения имени пользователя
Интеграция с Spring Security:
Автоматическое получение имени текущего пользователя
Пример реализации AuditorAware:
Кастомные реализации:
Возможность использовать ID пользователя вместо имени
Интеграция с кастомными системами аутентификации
Комбинирование с другими аннотациями аудита:
#Java #Training #Hard #Spring #SpringDataJPA #CreatedBy
Аннотация @CreatedBy используется в Spring Data для автоматического заполнения поля информацией о пользователе, создавшем сущность. Это часть механизма аудита Spring Data, позволяющего автоматически отслеживать, кто и когда создавал или изменял сущности. Аннотация находится в пакете org.springframework.data.annotation.
Параметры аннотации
Аннотация @CreatedBy не имеет параметров. Она применяется к полям сущности, которые должны автоматически заполняться информацией о создателе.
Пример использования:
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Document {
@CreatedBy
private String createdBy;
// Другие поля
}
Жизненный цикл аннотации
Инициализация:
Аннотация активируется при включении аудита через @EnableJpaAuditing
Требуется регистрация AuditingEntityListener для сущности
Выполнение:
Перед сохранением новой сущности (при вызове save())
Spring автоматически определяет текущего пользователя и устанавливает значение поля
Обновление:
Поле заполняется только при создании сущности
Не изменяется при последующих обновлениях
Механизмы Spring и настройки Spring Boot
AuditingEntityListener:
Класс, обрабатывающий события жизненного цикла сущности
Автоматически заполняет аннотированные поля
AuditorAware:
Интерфейс для получения информации о текущем пользователе
Требуется реализация для работы @CreatedBy
EnableJpaAuditing:
Аннотация для активации механизма аудита
Настройки Spring Boot
Активация аудита:
@Configuration
@EnableJpaAuditing
public class AuditConfig {
@Bean
public AuditorAware<String> auditorProvider() {
return () -> Optional.ofNullable(SecurityContextHolder.getContext())
.map(SecurityContext::getAuthentication)
.map(Authentication::getName);
}
}
Конфигурация сущности:
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Order {
@CreatedBy
private String createdBy;
@CreatedDate
private LocalDateTime createdDate;
// Другие поля
}
Настройки безопасности (если используется Spring Security):
spring.security.user.name=admin
spring.security.user.password=secret
Варианты настройки
Типы полей:
Может использоваться с любым типом (String, Long, UUID)
Чаще всего используется String для хранения имени пользователя
Интеграция с Spring Security:
Автоматическое получение имени текущего пользователя
Пример реализации AuditorAware:
public class SecurityAuditorAware implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
return Optional.ofNullable(SecurityContextHolder.getContext())
.map(SecurityContext::getAuthentication)
.filter(Authentication::isAuthenticated)
.map(Authentication::getName);
}
}
Кастомные реализации:
Возможность использовать ID пользователя вместо имени
Интеграция с кастомными системами аутентификации
Комбинирование с другими аннотациями аудита:
@CreatedBy
private String createdBy;
@CreatedDate
private LocalDateTime createdDate;
@LastModifiedBy
private String lastModifiedBy;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
#Java #Training #Hard #Spring #SpringDataJPA #CreatedBy
Аннотация @CreatedDate
Аннотация @CreatedDate используется в Spring Data для автоматического заполнения поля датой и временем создания сущности. Это часть механизма аудита Spring Data, который позволяет автоматически отслеживать временные метки создания и модификации сущностей. Аннотация находится в пакете org.springframework.data.annotation.
Параметры аннотации
Аннотация @CreatedDate не имеет параметров. Она применяется к полям сущности, которые должны автоматически заполняться временем создания.
Пример использования:
Поддерживаемые типы данных
Поле с аннотацией @CreatedDate может быть одного из следующих типов:
java.time.LocalDateTime
java.time.LocalDate
java.time.ZonedDateTime
java.util.Date
java.util.Calendar
java.sql.Timestamp
Long (для timestamp в миллисекундах)
Жизненный цикл аннотации
Инициализация:
Активируется при включении аудита через @EnableJpaAuditing
Требуется регистрация AuditingEntityListener для сущности
Выполнение:
Автоматически устанавливает текущую дату и время при первом сохранении сущности
Значение устанавливается один раз при создании и не изменяется при последующих обновлениях
Обновление:
Для отслеживания времени изменения следует использовать @LastModifiedDate
Механизмы Spring и настройки Spring Boot
AuditingEntityListener:
Обрабатывает события жизненного цикла сущности
Автоматически заполняет аннотированные поля датой/временем
EnableJpaAuditing:
Аннотация для активации механизма аудита
Настройки Spring Boot
Активация аудита в конфигурационном классе:
Конфигурация сущности:
Настройка часового пояса (опционально):
Варианты настройки и использования
Комбинирование с другими аннотациями аудита:
Использование разных типов даты/времени:
Кастомные форматы даты (при использовании с DTO):
Использование в проекциях Spring Data:
Особенности работы
Одноразовое заполнение:
Значение устанавливается только при первом сохранении сущности
Не изменяется при последующих обновлениях
Точность времени:
Зависит от базы данных и JPA-провайдера
Для высокой точности рекомендуется использовать java.time типы
Синхронизация времени:
Время берется с сервера, где выполняется приложение
Для распределенных систем рекомендуется использовать единый источник времени
#Java #Training #Hard #Spring #SpringDataJPA #CreatedDate
Аннотация @CreatedDate используется в Spring Data для автоматического заполнения поля датой и временем создания сущности. Это часть механизма аудита Spring Data, который позволяет автоматически отслеживать временные метки создания и модификации сущностей. Аннотация находится в пакете org.springframework.data.annotation.
Параметры аннотации
Аннотация @CreatedDate не имеет параметров. Она применяется к полям сущности, которые должны автоматически заполняться временем создания.
Пример использования:
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Document {
@CreatedDate
private LocalDateTime createdAt;
// Другие поля
}
Поддерживаемые типы данных
Поле с аннотацией @CreatedDate может быть одного из следующих типов:
java.time.LocalDateTime
java.time.LocalDate
java.time.ZonedDateTime
java.util.Date
java.util.Calendar
java.sql.Timestamp
Long (для timestamp в миллисекундах)
Жизненный цикл аннотации
Инициализация:
Активируется при включении аудита через @EnableJpaAuditing
Требуется регистрация AuditingEntityListener для сущности
Выполнение:
Автоматически устанавливает текущую дату и время при первом сохранении сущности
Значение устанавливается один раз при создании и не изменяется при последующих обновлениях
Обновление:
Для отслеживания времени изменения следует использовать @LastModifiedDate
Механизмы Spring и настройки Spring Boot
AuditingEntityListener:
Обрабатывает события жизненного цикла сущности
Автоматически заполняет аннотированные поля датой/временем
EnableJpaAuditing:
Аннотация для активации механизма аудита
Настройки Spring Boot
Активация аудита в конфигурационном классе:
@Configuration
@EnableJpaAuditing
public class AuditConfig {
// Дополнительные настройки при необходимости
}
Конфигурация сущности:
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Order {
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
// Другие поля
}
Настройка часового пояса (опционально):
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
Варианты настройки и использования
Комбинирование с другими аннотациями аудита:
@CreatedDate
private LocalDateTime createdAt;
@CreatedBy
private String createdBy;
@LastModifiedDate
private LocalDateTime updatedAt;
@LastModifiedBy
private String updatedBy;
Использование разных типов даты/времени:
@CreatedDate
private Date createdAt; // java.util.Date
@CreatedDate
private Long createdTimestamp; // timestamp в миллисекундах
Кастомные форматы даты (при использовании с DTO):
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@CreatedDate
private LocalDateTime createdAt;
Использование в проекциях Spring Data:
public interface OrderProjection {
@Value("#{target.createdAt}")
String getFormattedCreatedAt();
}
Особенности работы
Одноразовое заполнение:
Значение устанавливается только при первом сохранении сущности
Не изменяется при последующих обновлениях
Точность времени:
Зависит от базы данных и JPA-провайдера
Для высокой точности рекомендуется использовать java.time типы
Синхронизация времени:
Время берется с сервера, где выполняется приложение
Для распределенных систем рекомендуется использовать единый источник времени
#Java #Training #Hard #Spring #SpringDataJPA #CreatedDate
Аннотации @LastModifiedBy и @LastModifiedDate
Эти аннотации являются частью механизма аудита Spring Data и используются для автоматического отслеживания:
@LastModifiedBy - кто последним изменял сущность
@LastModifiedDate - когда были внесены последние изменения
Обе аннотации находятся в пакете org.springframework.data.annotation.
Аннотация @LastModifiedBy
Параметры
Как и @CreatedBy, аннотация не имеет параметров. Применяется к полям, которые должны хранить информацию о последнем редакторе.
Поддерживаемые типы
String (для имен пользователей)
Long/UUID (для ID пользователей)
Любой другой тип, возвращаемый реализацией AuditorAware
Пример использования
Аннотация @LastModifiedDate
Параметры
Не имеет параметров. Применяется к полям даты/времени.
Поддерживаемые типы
Те же, что и для @CreatedDate:
java.time типы (LocalDateTime, ZonedDateTime)
java.util.Date
Long (timestamp)
Пример использования
Комбинированное использование
Полный пример аудита
Особенности поведения
Инициализация:
@CreatedBy/Date заполняются только при создании
@LastModifiedBy/Date обновляются при каждом изменении
Сценарий обновления:
Настройка в Spring Boot
Обязательная конфигурация
Активация аудита:
Реализация AuditorAware (для @CreatedBy и @LastModifiedBy):
Дополнительные настройки
Для JPA репозиториев:
Настройка формата даты (опционально):
Практические рекомендации
Для веб-приложений:
Комбинируйте с Spring Security для автоматического определения пользователя
Используйте DTO с аннотацией @JsonFormat для красивого отображения дат
Для микросервисов:
Вместо имени пользователя можно хранить ID сервиса
Используйте единый часовой пояс (UTC) для всех сервисов
Оптимизация запросов:
Интеграция с историей изменений:
Можно создать отдельную таблицу для хранения полной истории изменений
Использовать @PreUpdate и @PrePersist для дополнительного логирования
Ограничения и решения
Проблема: Не обновляется при косвенных изменениях
Решение: Явно вызывать save() или использовать @Version
Проблема: Неточное время в кластере
Решение: Использовать NTP или временные сервисы
Проблема: Кастомные редакторы (например, системные задания)
Решение: Переопределить AuditorAware для специфических случаев
#Java #Training #Hard #Spring #SpringDataJPA #LastModifiedBy #LastModifiedDate
Эти аннотации являются частью механизма аудита Spring Data и используются для автоматического отслеживания:
@LastModifiedBy - кто последним изменял сущность
@LastModifiedDate - когда были внесены последние изменения
Обе аннотации находятся в пакете org.springframework.data.annotation.
Аннотация @LastModifiedBy
Параметры
Как и @CreatedBy, аннотация не имеет параметров. Применяется к полям, которые должны хранить информацию о последнем редакторе.
Поддерживаемые типы
String (для имен пользователей)
Long/UUID (для ID пользователей)
Любой другой тип, возвращаемый реализацией AuditorAware
Пример использования
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Document {
@LastModifiedBy
private String lastModifiedBy;
// Другие поля
}
Аннотация @LastModifiedDate
Параметры
Не имеет параметров. Применяется к полям даты/времени.
Поддерживаемые типы
Те же, что и для @CreatedDate:
java.time типы (LocalDateTime, ZonedDateTime)
java.util.Date
Long (timestamp)
Пример использования
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Document {
@LastModifiedDate
private LocalDateTime lastModifiedAt;
// Другие поля
}
Комбинированное использование
Полный пример аудита
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Product {
@Id
private Long id;
@CreatedBy
private String createdBy;
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedBy
private String lastModifiedBy;
@LastModifiedDate
private LocalDateTime lastModifiedAt;
// Бизнес-поля
private String name;
private BigDecimal price;
}
Особенности поведения
Инициализация:
@CreatedBy/Date заполняются только при создании
@LastModifiedBy/Date обновляются при каждом изменении
Сценарий обновления:
product.setPrice(new BigDecimal("99.99"));
productRepository.save(product);
Поля lastModifiedBy/At будут автоматически обновлены
Поля createdBy/At останутся без изменений
Настройка в Spring Boot
Обязательная конфигурация
Активация аудита:
@SpringBootApplication
@EnableJpaAuditing
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Реализация AuditorAware (для @CreatedBy и @LastModifiedBy):
@Bean
public AuditorAware<String> auditorAware() {
return () -> Optional.ofNullable(SecurityContextHolder.getContext())
.map(SecurityContext::getAuthentication)
.filter(Authentication::isAuthenticated)
.map(Authentication::getName);
}
Дополнительные настройки
Для JPA репозиториев:
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
Настройка формата даты (опционально):
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=UTC
Практические рекомендации
Для веб-приложений:
Комбинируйте с Spring Security для автоматического определения пользователя
Используйте DTO с аннотацией @JsonFormat для красивого отображения дат
Для микросервисов:
Вместо имени пользователя можно хранить ID сервиса
Используйте единый часовой пояс (UTC) для всех сервисов
Оптимизация запросов:
@Query("SELECT p FROM Product p WHERE p.lastModifiedAt > :since")
List<Product> findRecentlyModified(@Param("since") LocalDateTime since);
Интеграция с историей изменений:
Можно создать отдельную таблицу для хранения полной истории изменений
Использовать @PreUpdate и @PrePersist для дополнительного логирования
Ограничения и решения
Проблема: Не обновляется при косвенных изменениях
Решение: Явно вызывать save() или использовать @Version
Проблема: Неточное время в кластере
Решение: Использовать NTP или временные сервисы
Проблема: Кастомные редакторы (например, системные задания)
Решение: Переопределить AuditorAware для специфических случаев
#Java #Training #Hard #Spring #SpringDataJPA #LastModifiedBy #LastModifiedDate
Аннотация @Version
Аннотация @Version используется в JPA для реализации оптимистичной блокировки (optimistic locking) - механизма контроля параллельного доступа к данным без использования явных блокировок на уровне базы данных. Находится в пакете javax.persistence.
Параметры аннотации
Аннотация не имеет параметров. Применяется к единственному полю сущности, которое должно быть:
Числовым типом (int, Integer, long, Long)
Типом java.sql.Timestamp
Пример использования
Жизненный цикл аннотации
Инициализация:
При создании сущности поле получает значение 0 (или текущее время для Timestamp)
Обновление:
При каждом обновлении сущности значение автоматически увеличивается на 1
JPA проверяет, что значение в БД совпадает с исходным значением перед обновлением
Конфликт:
Если значение в БД изменилось (другой транзакцией), выбрасывается OptimisticLockException
Механизм работы
При чтении сущности:
При обновлении:
Выполняется SQL вида:
Если версия изменилась:
Количество обновленных строк = 0 → OptimisticLockException
Обработка исключений:
Практическое использование
Базовый сценарий:
Проверка версии вручную:
Использование DTO:
Особенности реализации
Типы полей:
Для числовых типов: последовательное увеличение
Для Timestamp: текущее время сервера
Поведение при:
Создании: устанавливается 0
Клонировании: версия не копируется
Удалении: проверка версии не выполняется (настраивается через @OptimisticLocking)
Производительность:
Минимальные накладные расходы
Не требует блокировок в БД
Альтернативы и дополнения
Пессимистичная блокировка:
Дополнительные аннотации Hibernate:
@OptimisticLocking - для настройки поведения
@DynamicUpdate - обновлять только измененные поля
Кастомные стратегии:
Реализация собственного механизма через @PreUpdate
#Java #Training #Hard #Spring #SpringDataJPA #Version
Аннотация @Version используется в JPA для реализации оптимистичной блокировки (optimistic locking) - механизма контроля параллельного доступа к данным без использования явных блокировок на уровне базы данных. Находится в пакете javax.persistence.
Параметры аннотации
Аннотация не имеет параметров. Применяется к единственному полю сущности, которое должно быть:
Числовым типом (int, Integer, long, Long)
Типом java.sql.Timestamp
Пример использования
@Entity
public class Product {
@Id
private Long id;
@Version
private Integer version;
// другие поля
}
Жизненный цикл аннотации
Инициализация:
При создании сущности поле получает значение 0 (или текущее время для Timestamp)
Обновление:
При каждом обновлении сущности значение автоматически увеличивается на 1
JPA проверяет, что значение в БД совпадает с исходным значением перед обновлением
Конфликт:
Если значение в БД изменилось (другой транзакцией), выбрасывается OptimisticLockException
Механизм работы
При чтении сущности:
Product product = em.find(Product.class, 1L);
// product.version = 1 (текущее значение в БД)
При обновлении:
product.setPrice(newPrice);
em.merge(product);
Выполняется SQL вида:
UPDATE product
SET ..., version = version + 1
WHERE id = 1 AND version = 1
Если версия изменилась:
Количество обновленных строк = 0 → OptimisticLockException
Обработка исключений:
@ExceptionHandler(OptimisticLockException.class)
public ResponseEntity<String> handleConflict(OptimisticLockException ex) {
return ResponseEntity.status(HttpStatus.CONFLICT).body("Объект был изменен другим пользователем");
}
Практическое использование
Базовый сценарий:
@Service
@Transactional
public class ProductService {
public void updatePrice(Long id, BigDecimal newPrice) {
Product product = productRepository.findById(id).orElseThrow();
product.setPrice(newPrice);
// При коммите транзакции версия автоматически увеличится
}
}
Проверка версии вручную:
public void updateWithVersionCheck(Long id, Integer expectedVersion, Product update) {
Product product = productRepository.findById(id).orElseThrow();
if (!product.getVersion().equals(expectedVersion)) {
throw new OptimisticLockException("Версия не совпадает");
}
// ... обновление
}
Использование DTO:
public class ProductDto {
private Long id;
private Integer version;
// другие поля
public Product toEntity() {
Product product = new Product();
product.setId(this.id);
product.setVersion(this.version);
// ...
return product;
}
}
Особенности реализации
Типы полей:
Для числовых типов: последовательное увеличение
Для Timestamp: текущее время сервера
Поведение при:
Создании: устанавливается 0
Клонировании: версия не копируется
Удалении: проверка версии не выполняется (настраивается через @OptimisticLocking)
Производительность:
Минимальные накладные расходы
Не требует блокировок в БД
Альтернативы и дополнения
Пессимистичная блокировка:
@Lock(LockModeType.PESSIMISTIC_WRITE)
Product findByIdForUpdate(Long id);
Дополнительные аннотации Hibernate:
@OptimisticLocking - для настройки поведения
@DynamicUpdate - обновлять только измененные поля
Кастомные стратегии:
Реализация собственного механизма через @PreUpdate
#Java #Training #Hard #Spring #SpringDataJPA #Version
Аннотация @PersistenceContext
Аннотация @PersistenceContext используется для внедрения (inject) контейнера управляемых JPA-сущностей (EntityManager) в Spring-приложение. Она принадлежит к спецификации Jakarta Persistence API (JPA) и находится в пакете jakarta.persistence.
Spring автоматически управляет жизненным циклом EntityManager, обеспечивая корректное открытие и закрытие сессий, а также интеграцию с транзакциями.
Параметры аннотации
name (необязательный)
Тип: String
Описание: Имя единицы персистентности (persistence-unit), если их несколько в persistence.xml.
Пример:
unitName (необязательный)
Тип: String
Описание: Альтернатива name, явно указывает имя persistence-unit.
Пример:
type (необязательный)
Тип: PersistenceContextType (TRANSACTION или EXTENDED)
Значение по умолчанию: TRANSACTION
Описание:
TRANSACTION (по умолчанию): EntityManager привязан к текущей транзакции и закрывается после её завершения.
EXTENDED: EntityManager живет дольше транзакции (используется в Stateful-бинах, например, в JSF).
Пример:
properties (необязательный)
Тип: Map<String, Object>
Описание: Дополнительные свойства для настройки EntityManager (например, hibernate.jdbc.batch_size).
Пример:
Жизненный цикл @PersistenceContext
Инициализация
При старте Spring создает прокси для EntityManager, который делегирует вызовы реальному EntityManager только внутри транзакции.
Если используется EXTENDED, EntityManager сохраняет состояние между транзакциями.
Работа в транзакции
В режиме TRANSACTION (по умолчанию) EntityManager автоматически открывается при старте транзакции (@Transactional) и закрывается после её завершения.
Уничтожение
В режиме TRANSACTION EntityManager закрывается после завершения транзакции.
В режиме EXTENDED EntityManager живет до уничтожения бина (например, при завершении HTTP-сессии в веб-приложении).
Механизмы Spring и настройки Spring Boot
1. Как Spring Boot настраивает EntityManager?
Spring Boot автоматически создает EntityManagerFactory на основе:
Настроек DataSource (из application.properties).
JPA-провайдера (Hibernate по умолчанию).
2. Альтернативные варианты настройки
Несколько источников данных:
Если нужно несколько EntityManager, можно определить несколько @Bean в конфигурации:
Ручное управление транзакциями:
Можно использовать EntityManager без @Transactional, но тогда нужно вручную вызывать em.getTransaction().begin() и commit().
Аннотация @PersistenceUnit
Аннотация @PersistenceUnit используется для внедрения EntityManagerFactory (а не самого EntityManager). Полезна, когда требуется создавать EntityManager вручную.
Параметры
unitName (необязательный) – имя persistence-unit (если их несколько).
Пример использования
Когда использовать @PersistenceUnit вместо @PersistenceContext?
Если нужно полное управление жизненным циклом EntityManager (например, в batch-обработке).
Если требуется несколько EntityManager в одном методе.
#Java #Training #Hard #Spring #SpringDataJPA #PersistenceUnit #PersistenceContext
Аннотация @PersistenceContext используется для внедрения (inject) контейнера управляемых JPA-сущностей (EntityManager) в Spring-приложение. Она принадлежит к спецификации Jakarta Persistence API (JPA) и находится в пакете jakarta.persistence.
Spring автоматически управляет жизненным циклом EntityManager, обеспечивая корректное открытие и закрытие сессий, а также интеграцию с транзакциями.
Параметры аннотации
name (необязательный)
Тип: String
Описание: Имя единицы персистентности (persistence-unit), если их несколько в persistence.xml.
Пример:
@PersistenceContext(name = "myPersistenceUnit")
private EntityManager entityManager;
unitName (необязательный)
Тип: String
Описание: Альтернатива name, явно указывает имя persistence-unit.
Пример:
@PersistenceContext(unitName = "myPersistenceUnit")
private EntityManager entityManager;
type (необязательный)
Тип: PersistenceContextType (TRANSACTION или EXTENDED)
Значение по умолчанию: TRANSACTION
Описание:
TRANSACTION (по умолчанию): EntityManager привязан к текущей транзакции и закрывается после её завершения.
EXTENDED: EntityManager живет дольше транзакции (используется в Stateful-бинах, например, в JSF).
Пример:
@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;
properties (необязательный)
Тип: Map<String, Object>
Описание: Дополнительные свойства для настройки EntityManager (например, hibernate.jdbc.batch_size).
Пример:
@PersistenceContext(properties = {
@PersistenceProperty(name = "hibernate.jdbc.batch_size", value = "20")
})
private EntityManager entityManager;
Жизненный цикл @PersistenceContext
Инициализация
При старте Spring создает прокси для EntityManager, который делегирует вызовы реальному EntityManager только внутри транзакции.
Если используется EXTENDED, EntityManager сохраняет состояние между транзакциями.
Работа в транзакции
В режиме TRANSACTION (по умолчанию) EntityManager автоматически открывается при старте транзакции (@Transactional) и закрывается после её завершения.
Уничтожение
В режиме TRANSACTION EntityManager закрывается после завершения транзакции.
В режиме EXTENDED EntityManager живет до уничтожения бина (например, при завершении HTTP-сессии в веб-приложении).
Механизмы Spring и настройки Spring Boot
1. Как Spring Boot настраивает EntityManager?
Spring Boot автоматически создает EntityManagerFactory на основе:
Настроек DataSource (из application.properties).
JPA-провайдера (Hibernate по умолчанию).
2. Альтернативные варианты настройки
Несколько источников данных:
Если нужно несколько EntityManager, можно определить несколько @Bean в конфигурации:
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("com.example.domain");
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
return em;
}
Ручное управление транзакциями:
Можно использовать EntityManager без @Transactional, но тогда нужно вручную вызывать em.getTransaction().begin() и commit().
Аннотация @PersistenceUnit
Аннотация @PersistenceUnit используется для внедрения EntityManagerFactory (а не самого EntityManager). Полезна, когда требуется создавать EntityManager вручную.
Параметры
unitName (необязательный) – имя persistence-unit (если их несколько).
Пример использования
@PersistenceUnit
private EntityManagerFactory emf;
public void someMethod() {
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
// ... операции с БД ...
em.getTransaction().commit();
} finally {
em.close();
}
}
Когда использовать @PersistenceUnit вместо @PersistenceContext?
Если нужно полное управление жизненным циклом EntityManager (например, в batch-обработке).
Если требуется несколько EntityManager в одном методе.
#Java #Training #Hard #Spring #SpringDataJPA #PersistenceUnit #PersistenceContext
Аннотация @EnableJpaAuditing
Аннотация @EnableJpaAuditing активирует поддержку аудита сущностей JPA в Spring Data. Она позволяет автоматически отслеживать изменения в сущностях, такие как:
Кто создал или изменил запись (createdBy, lastModifiedBy).
Когда запись была создана или изменена (createdDate, lastModifiedDate).
Параметры аннотации
auditorAwareRef (необязательный)
Тип: String
Описание: Указывает имя бина, реализующего интерфейс AuditorAware<T>. Этот бин предоставляет информацию о текущем пользователе (например, из Spring Security).
Пример:
dateTimeProviderRef (необязательный)
Тип: String
Описание: Указывает имя бина, реализующего DateTimeProvider. Позволяет кастомизировать логику получения текущей даты/времени (например, для тестов).
Пример:
setDates (необязательный)
Тип: boolean
Значение по умолчанию: true
Описание: Если false, автоматическое обновление полей createdDate и lastModifiedDate отключается.
modifyOnCreate (необязательный)
Тип: boolean
Значение по умолчанию: true
Описание: Если false, поле lastModifiedDate не обновляется при создании сущности (только createdDate).
Жизненный цикл аудита
Инициализация
При старте приложения Spring ищет классы с @EnableJpaAuditing и регистрирует AuditingEntityListener.
Если указан auditorAwareRef, Spring внедряет соответствующий бин.
Сохранение/обновление сущности
Перед вставкой (@PrePersist) автоматически заполняются:
createdBy и createdDate (если поддерживается).
Перед обновлением (@PreUpdate) заполняются:
lastModifiedBy и lastModifiedDate.
Уничтожение
Аудит не влияет на удаление сущностей, но можно добавить @PreRemove логику вручную.
Механизмы Spring и настройки Spring Boot
1. Как работает аудит в Spring Data JPA?
AuditingEntityListener – JPA-колбек, который обрабатывает события @PrePersist и @PreUpdate.
AuditorAware – интерфейс для получения информации о текущем пользователе.
@CreatedDate, @LastModifiedDate, @CreatedBy, @LastModifiedBy – аннотации для полей сущности.
2. Настройка сущности
3. Конфигурация Spring Boot
Если используется Spring Boot, можно не указывать @EnableJpaAuditing вручную, если:
Есть бин AuditorAware.
Включен spring.data.jpa.repositories.bootstrap-mode=default (по умолчанию).
Пример application.properties:
4. Интеграция с Spring Security
Если приложение использует Spring Security, AuditorAware может возвращать текущего пользователя:
Варианты настройки
Отключение аудита для отдельных полей
Не аннотировать поле @CreatedBy, если оно не нужно.
Кастомные даты
Реализовать DateTimeProvider, если требуется использовать не Instant.now(), а другую временную зону.
Аудит без Spring Security
Можно возвращать фиксированное значение (например, "system"):
#Java #Training #Hard #Spring #SpringDataJPA #EnableJpaAuditing
Аннотация @EnableJpaAuditing активирует поддержку аудита сущностей JPA в Spring Data. Она позволяет автоматически отслеживать изменения в сущностях, такие как:
Кто создал или изменил запись (createdBy, lastModifiedBy).
Когда запись была создана или изменена (createdDate, lastModifiedDate).
Параметры аннотации
auditorAwareRef (необязательный)
Тип: String
Описание: Указывает имя бина, реализующего интерфейс AuditorAware<T>. Этот бин предоставляет информацию о текущем пользователе (например, из Spring Security).
Пример:
@EnableJpaAuditing(auditorAwareRef = "auditorProvider")
@Configuration
public class JpaConfig {
@Bean
public AuditorAware<String> auditorProvider() {
return () -> Optional.of("admin"); // Возвращает текущего пользователя
}
}
dateTimeProviderRef (необязательный)
Тип: String
Описание: Указывает имя бина, реализующего DateTimeProvider. Позволяет кастомизировать логику получения текущей даты/времени (например, для тестов).
Пример:
@EnableJpaAuditing(dateTimeProviderRef = "customDateTimeProvider")
@Configuration
public class JpaConfig {
@Bean
public DateTimeProvider customDateTimeProvider() {
return () -> Optional.of(Instant.now());
}
}
setDates (необязательный)
Тип: boolean
Значение по умолчанию: true
Описание: Если false, автоматическое обновление полей createdDate и lastModifiedDate отключается.
modifyOnCreate (необязательный)
Тип: boolean
Значение по умолчанию: true
Описание: Если false, поле lastModifiedDate не обновляется при создании сущности (только createdDate).
Жизненный цикл аудита
Инициализация
При старте приложения Spring ищет классы с @EnableJpaAuditing и регистрирует AuditingEntityListener.
Если указан auditorAwareRef, Spring внедряет соответствующий бин.
Сохранение/обновление сущности
Перед вставкой (@PrePersist) автоматически заполняются:
createdBy и createdDate (если поддерживается).
Перед обновлением (@PreUpdate) заполняются:
lastModifiedBy и lastModifiedDate.
Уничтожение
Аудит не влияет на удаление сущностей, но можно добавить @PreRemove логику вручную.
Механизмы Spring и настройки Spring Boot
1. Как работает аудит в Spring Data JPA?
AuditingEntityListener – JPA-колбек, который обрабатывает события @PrePersist и @PreUpdate.
AuditorAware – интерфейс для получения информации о текущем пользователе.
@CreatedDate, @LastModifiedDate, @CreatedBy, @LastModifiedBy – аннотации для полей сущности.
2. Настройка сущности
@Entity
@EntityListeners(AuditingEntityListener.class) // Включение аудита
public class User {
@Id
@GeneratedValue
private Long id;
@CreatedDate
private Instant createdDate;
@LastModifiedDate
private Instant lastModifiedDate;
@CreatedBy
private String createdBy;
@LastModifiedBy
private String lastModifiedBy;
}
3. Конфигурация Spring Boot
Если используется Spring Boot, можно не указывать @EnableJpaAuditing вручную, если:
Есть бин AuditorAware.
Включен spring.data.jpa.repositories.bootstrap-mode=default (по умолчанию).
Пример application.properties:
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
4. Интеграция с Spring Security
Если приложение использует Spring Security, AuditorAware может возвращать текущего пользователя:
@Bean
public AuditorAware<String> auditorAware() {
return () -> Optional.ofNullable(SecurityContextHolder.getContext())
.map(SecurityContext::getAuthentication)
.map(Authentication::getName);
}
Варианты настройки
Отключение аудита для отдельных полей
Не аннотировать поле @CreatedBy, если оно не нужно.
Кастомные даты
Реализовать DateTimeProvider, если требуется использовать не Instant.now(), а другую временную зону.
Аудит без Spring Security
Можно возвращать фиксированное значение (например, "system"):
@Bean
public AuditorAware<String> auditorAware() {
return () -> Optional.of("system");
}
#Java #Training #Hard #Spring #SpringDataJPA #EnableJpaAuditing
Аннотация @EntityListeners
Аннотация @EntityListeners является частью спецификации JPA (Jakarta Persistence API) и позволяет привязать кастомные слушатели (listeners) к сущностям JPA.
Эти слушатели могут перехватывать события жизненного цикла сущности, такие как:
@PrePersist (перед сохранением)
@PostPersist (после сохранения)
@PreUpdate (перед обновлением)
@PostUpdate (после обновлением)
@PreRemove (перед удалением)
@PostRemove (после удалением)
@PostLoad (после загрузкой из БД)
Аннотация находится в пакете jakarta.persistence и применяется на уровне класса сущности.
Параметры аннотации
value (обязательный)
Тип: Массив классов (Class<?>[])
Описание: Принимает один или несколько классов-слушателей, которые должны реализовывать callback-методы JPA.
Пример:
Жизненный цикл слушателей
Регистрация слушателей
При загрузке метаданных JPA провайдер (Hibernate) регистрирует указанные классы-слушатели для сущности.
Вызов callback-методов
При наступлении соответствующего события жизненного цикла JPA вызывает методы слушателей в порядке их объявления.
Порядок выполнения
Если для сущности определено несколько слушателей, их методы выполняются в порядке объявления в аннотации.
Глобальные слушатели (зарегистрированные в orm.xml) выполняются после локальных.
Механизмы работы в Spring
1. Интеграция с Spring
Spring автоматически поддерживает DI в JPA Entity Listeners, если они являются Spring-бинами.
Для этого нужно:
Пометить класс-слушатель как @Component
Зарегистрировать его в Spring-контексте
2. Пример Spring-совместимого слушателя
3. Конфигурация в Spring Boot
Spring Boot автоматически настраивает поддержку Entity Listeners через:
Автоконфигурацию JPA (HibernateJpaAutoConfiguration)
Поддержку инъекции зависимостей в слушатели
Варианты использования
1. Аудит изменений
2. Валидация перед сохранением
3. Кеширование
Ограничения и особенности
Контекст выполнения
Callback-методы выполняются в том же контексте транзакции, что и основная операция.
Исключения
Выброс исключения в callback-методе приводит к откату транзакции.
Порядок выполнения
Методы выполняются в порядке:
Callback-методы самой сущности
Локальные @EntityListeners
Глобальные слушатели
DI ограничения
В чистом JPA слушатели не поддерживают инъекцию зависимостей
В Spring DI работает только для Spring-бинов
#Java #Training #Hard #Spring #SpringDataJPA #EntityListeners
Аннотация @EntityListeners является частью спецификации JPA (Jakarta Persistence API) и позволяет привязать кастомные слушатели (listeners) к сущностям JPA.
Эти слушатели могут перехватывать события жизненного цикла сущности, такие как:
@PrePersist (перед сохранением)
@PostPersist (после сохранения)
@PreUpdate (перед обновлением)
@PostUpdate (после обновлением)
@PreRemove (перед удалением)
@PostRemove (после удалением)
@PostLoad (после загрузкой из БД)
Аннотация находится в пакете jakarta.persistence и применяется на уровне класса сущности.
Параметры аннотации
value (обязательный)
Тип: Массив классов (Class<?>[])
Описание: Принимает один или несколько классов-слушателей, которые должны реализовывать callback-методы JPA.
Пример:
@Entity
@EntityListeners({AuditListener.class, CacheInvalidationListener.class})
public class User {
// поля сущности
}
Жизненный цикл слушателей
Регистрация слушателей
При загрузке метаданных JPA провайдер (Hibernate) регистрирует указанные классы-слушатели для сущности.
Вызов callback-методов
При наступлении соответствующего события жизненного цикла JPA вызывает методы слушателей в порядке их объявления.
Порядок выполнения
Если для сущности определено несколько слушателей, их методы выполняются в порядке объявления в аннотации.
Глобальные слушатели (зарегистрированные в orm.xml) выполняются после локальных.
Механизмы работы в Spring
1. Интеграция с Spring
Spring автоматически поддерживает DI в JPA Entity Listeners, если они являются Spring-бинами.
Для этого нужно:
Пометить класс-слушатель как @Component
Зарегистрировать его в Spring-контексте
2. Пример Spring-совместимого слушателя
@Component
public class AuditListener {
@PrePersist
public void prePersist(Object entity) {
System.out.println("PrePersist: " + entity);
}
@PreUpdate
public void preUpdate(Object entity) {
System.out.println("PreUpdate: " + entity);
}
}
3. Конфигурация в Spring Boot
Spring Boot автоматически настраивает поддержку Entity Listeners через:
Автоконфигурацию JPA (HibernateJpaAutoConfiguration)
Поддержку инъекции зависимостей в слушатели
Варианты использования
1. Аудит изменений
public class AuditListener {
@PrePersist
public void setCreationDate(Object entity) {
if (entity instanceof Auditable) {
((Auditable) entity).setCreatedAt(LocalDateTime.now());
}
}
}
2. Валидация перед сохранением
public class ValidationListener {
@PrePersist
@PreUpdate
public void validate(Object entity) {
if (entity instanceof Validatable) {
((Validatable) entity).validate();
}
}
}
3. Кеширование
public class CacheListener {
@PostPersist
@PostUpdate
@PostRemove
public void invalidateCache(Object entity) {
CacheManager.evict(entity.getClass(), entity.getId());
}
}
Ограничения и особенности
Контекст выполнения
Callback-методы выполняются в том же контексте транзакции, что и основная операция.
Исключения
Выброс исключения в callback-методе приводит к откату транзакции.
Порядок выполнения
Методы выполняются в порядке:
Callback-методы самой сущности
Локальные @EntityListeners
Глобальные слушатели
DI ограничения
В чистом JPA слушатели не поддерживают инъекцию зависимостей
В Spring DI работает только для Spring-бинов
#Java #Training #Hard #Spring #SpringDataJPA #EntityListeners
Аннотация @Projection
Аннотация @Projection используется в Spring Data для определения проекций - специальных интерфейсов или классов, которые позволяют выбирать только определенные поля из сущностей.
Это полезно для:
Оптимизации запросов (избегания select *)
Создания DTO на лету
Кастомизации JSON-представления REST API
Проекции находятся в пакете org.springframework.data.rest.core.config.Projection и применяются к интерфейсам или классам.
Параметры аннотации
types (обязательный)
Тип: Class<?>[]
Описание: Указывает сущности, к которым применяется проекция
Пример:
name (необязательный)
Тип: String
Описание: Задает имя проекции для использования в Spring Data REST
Пример:
Типы проекций
1. Интерфейсные проекции
Наиболее распространенный подход:
2. Классовые проекции (DTO)
Используются классы вместо интерфейсов:
3. Динамические проекции
Можно создавать проекции на лету через SpEL:
Жизненный цикл проекций
Объявление проекции
Создается интерфейс/класс с аннотацией @Projection
Определяются методы, соответствующие полям сущности
Использование в репозитории
Spring Data создает прокси-реализацию при выполнении запроса
Преобразование результатов
После выполнения запроса результаты маппятся на проекцию
Механизмы Spring Data
1. Автоматический маппинг
Spring Data автоматически:
Анализирует методы проекции
Создает соответствующий SQL (только выбранные поля)
Преобразует результат в проекцию
2. Интеграция с репозиториями
3. Поддержка в Spring Data REST
Проекции можно активировать через параметр запроса:
Примеры использования
1. Базовый пример
2. Комплексная проекция
3. Вложенные проекции
Настройки Spring Boot
Автоконфигурация
Spring Boot автоматически настраивает поддержку проекций через SpringDataWebConfiguration
Ручная регистрация
Можно явно зарегистрировать проекции:
Настройка REST
В application.properties:
#Java #Training #Hard #Spring #SpringDataJPA #Projection
Аннотация @Projection используется в Spring Data для определения проекций - специальных интерфейсов или классов, которые позволяют выбирать только определенные поля из сущностей.
Это полезно для:
Оптимизации запросов (избегания select *)
Создания DTO на лету
Кастомизации JSON-представления REST API
Проекции находятся в пакете org.springframework.data.rest.core.config.Projection и применяются к интерфейсам или классам.
Параметры аннотации
types (обязательный)
Тип: Class<?>[]
Описание: Указывает сущности, к которым применяется проекция
Пример:
@Projection(types = {User.class})
public interface UserSummary {
String getUsername();
String getEmail();
}
name (необязательный)
Тип: String
Описание: Задает имя проекции для использования в Spring Data REST
Пример:
@Projection(name = "summary", types = User.class)
public interface UserSummary {...}
Типы проекций
1. Интерфейсные проекции
Наиболее распространенный подход:
@Projection(types = User.class)
public interface UserView {
String getUsername();
String getEmail();
// Можно включать связанные сущности
@Value("#{target.department.name}")
String getDepartmentName();
}
2. Классовые проекции (DTO)
Используются классы вместо интерфейсов:
@Projection(types = User.class)
public class UserDto {
private final String username;
private final String email;
public UserDto(String username, String email) {
this.username = username;
this.email = email;
}
// Геттеры
}
3. Динамические проекции
Можно создавать проекции на лету через SpEL:
@Projection(types = User.class)
public interface DynamicUserView {
@Value("#{target.username + ' (' + target.email + ')'}")
String getDisplayName();
}
Жизненный цикл проекций
Объявление проекции
Создается интерфейс/класс с аннотацией @Projection
Определяются методы, соответствующие полям сущности
Использование в репозитории
Spring Data создает прокси-реализацию при выполнении запроса
Преобразование результатов
После выполнения запроса результаты маппятся на проекцию
Механизмы Spring Data
1. Автоматический маппинг
Spring Data автоматически:
Анализирует методы проекции
Создает соответствующий SQL (только выбранные поля)
Преобразует результат в проекцию
2. Интеграция с репозиториями
public interface UserRepository extends JpaRepository<User, Long> {
<T> List<T> findBy(Class<T> type);
UserSummary findSummaryById(Long id);
}
3. Поддержка в Spring Data REST
Проекции можно активировать через параметр запроса:
GET /users/1?projection=summary
Примеры использования
1. Базовый пример
@Entity
public class User {
private Long id;
private String username;
private String email;
// геттеры/сеттеры
}
@Projection(types = User.class)
public interface UserSummary {
String getUsername();
String getEmail();
}
// В репозитории
UserSummary findSummaryById(Long id);
2. Комплексная проекция
@Projection(types = {User.class, Department.class})
public interface UserDetailView {
String getUsername();
@Value("#{target.department.name}")
String getDepartmentName();
default String getDisplayInfo() {
return getUsername() + " from " + getDepartmentName();
}
}
3. Вложенные проекции
@Projection(types = Order.class)
public interface OrderView {
String getOrderNumber();
@Value("#{target.customer}")
CustomerView getCustomer();
}
@Projection(types = Customer.class)
public interface CustomerView {
String getName();
}
Настройки Spring Boot
Автоконфигурация
Spring Boot автоматически настраивает поддержку проекций через SpringDataWebConfiguration
Ручная регистрация
Можно явно зарегистрировать проекции:
@Configuration
public class ProjectionConfig {
@Bean
public ProjectionDefinitionRegistrar projectionRegistrar() {
return registrar -> {
registrar.addProjection(UserSummary.class);
};
}
}
Настройка REST
В application.properties:
spring.data.rest.default-projection=summary
#Java #Training #Hard #Spring #SpringDataJPA #Projection