Java for Beginner
672 subscribers
540 photos
155 videos
12 files
827 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Кастомизация конвертеров:

Spring Boot позволяет регистрировать конвертеры вручную через конфигурацию EntityManagerFactory.

Пример ручной регистрации конвертера:
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("com.example.domain");

HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);

Map<String, Object> properties = new HashMap<>();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
properties.put("hibernate.hbm2ddl.auto", "update");
em.setJpaPropertyMap(properties);

// Регистрация конвертера
em.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
em.getJpaPropertyMap().put("javax.persistence.bean.validation.mode", "none");
em.getJpaPropertyMap().put("hibernate.session_factory.interceptor", new EmptyInterceptor() {
@Override
public void onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
// Логика перехвата
}
});

return em;
}


Варианты настройки

Автоматическое применение:

Используйте @Converter(autoApply = true), если конвертер должен применяться ко всем атрибутам соответствующего типа.

Ручное применение:
Используйте @Convert(converter = MyConverter.class), если конвертер должен применяться только к конкретным атрибутам.

Кастомизация маппинга:
Для сложных сценариев можно использовать @Embeddable и @Embedded в сочетании с конвертерами.

Пример использования @Embeddable:
@Embeddable
public class Address {
private String street;
private String city;

@Convert(converter = ZipCodeConverter.class)
private String zipCode;
}


Использование вложенных объектов:
Конвертеры могут применяться к атрибутам вложенных объектов через параметр attributeName в @Convert.

#Java #Training #Hard #Spring #SpringDataJPA #Convert #Converter
Аннотации @PrePersist и @PostPersist

Аннотации @PrePersist и @PostPersist используются в Java Persistence API (JPA) для указания методов обратного вызова (callback), которые выполняются до и после сохранения сущности в базу данных. Они находятся в пакете javax.persistence (или jakarta.persistence в Jakarta EE).

@PrePersist: Метод, аннотированный @PrePersist, вызывается перед тем, как сущность будет сохранена в базу данных (перед выполнением persist).
@PostPersist: Метод, аннотированный @PostPersist, вызывается после того, как сущность была успешно сохранена в базу данных (после выполнения persist).

Эти аннотации полезны для выполнения дополнительной логики, например, инициализации значений, валидации или логирования, до или после сохранения сущности.

Параметры и настройки

Аннотации @PrePersist и @PostPersist не принимают параметров. Они применяются к методам сущности, которые должны быть вызваны в соответствующий момент жизненного цикла сущности.

Требования к методам:

Метод должен быть void и не принимать параметров.
Метод может иметь любой модификатор доступа (public, protected, private).
Метод не должен быть статическим.


Пример использования:
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

@PrePersist
private void beforePersist() {
System.out.println("Before persisting user: " + this.name);
if (this.name == null) {
this.name = "DEFAULT_NAME";
}
}

@PostPersist
private void afterPersist() {
System.out.println("User persisted with ID: " + this.id);
}
}


Жизненный цикл

@PrePersist:
Вызывается перед выполнением операции persist в EntityManager.
Используется для инициализации или валидации данных перед сохранением.
Пример: установка значений по умолчанию, генерация UUID, проверка обязательных полей.


@PostPersist:
Вызывается после успешного выполнения операции persist и фиксации транзакции.
Используется для выполнения действий после сохранения, например, логирования или отправки уведомлений.
Пример: логирование ID сохраненной сущности, отправка события в систему сообщений.


Логирование жизненного цикла:

Для отладки можно включить логирование жизненного цикла сущностей через Hibernate:
spring.jpa.properties.hibernate.ejb.event.post-persist=org.hibernate.event.internal.DefaultPersistEventListener


Кастомизация событий:
Если требуется более сложная обработка событий, можно использовать @EntityListeners для определения слушателей сущностей.

Пример использования @EntityListeners:
@Entity
@EntityListeners(UserListener.class)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;
}

public class UserListener {
@PrePersist
public void beforePersist(User user) {
System.out.println("Before persisting user: " + user.getName());
}

@PostPersist
public void afterPersist(User user) {
System.out.println("User persisted with ID: " + user.getId());
}
}


Варианты настройки

Использование @EntityListeners:
Для разделения логики можно вынести методы обратного вызова в отдельный класс и использовать @EntityListeners.

Глобальные слушатели:
Для применения логики ко всем сущностям можно зарегистрировать глобальный слушатель через Hibernate.

Пример глобального слушателя:
public class GlobalEntityListener {
@PrePersist
public void beforePersist(Object entity) {
System.out.println("Before persisting entity: " + entity.getClass().getSimpleName());
}

@PostPersist
public void afterPersist(Object entity) {
System.out.println("Entity persisted: " + entity.getClass().getSimpleName());
}
}


Регистрация глобального слушателя в Hibernate:
spring.jpa.properties.hibernate.ejb.event.pre-persist=com.example.GlobalEntityListener
spring.jpa.properties.hibernate.ejb.event.post-persist=com.example.GlobalEntityListener


#Java #Training #Hard #Spring #SpringDataJPA #PrePersist #PostPersist
Аннотации @PreUpdate и @PostUpdate

Аннотации @PreUpdate и @PostUpdate используются в Java Persistence API (JPA) для указания методов обратного вызова (callback), которые выполняются до и после обновления сущности в базе данных. Они находятся в пакете javax.persistence (или jakarta.persistence в Jakarta EE).

@PreUpdate: Метод, аннотированный @PreUpdate, вызывается перед тем, как сущность будет обновлена в базе данных (перед выполнением update).
@PostUpdate: Метод, аннотированный @PostUpdate, вызывается после того, как сущность была успешно обновлена в базе данных (после выполнения update).

Эти аннотации полезны для выполнения дополнительной логики, например, валидации, логирования или обновления зависимых данных, до или после обновления сущности.

Параметры и настройки

Аннотации @PreUpdate и @PostUpdate не принимают параметров. Они применяются к методам сущности, которые должны быть вызваны в соответствующий момент жизненного цикла сущности.

Требования к методам:
Метод должен быть void и не принимать параметров.
Метод может иметь любой модификатор доступа (public, protected, private).
Метод не должен быть статическим.


Пример использования:
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

@PreUpdate
private void beforeUpdate() {
System.out.println("Before updating user: " + this.name);
if (this.name == null) {
this.name = "DEFAULT_NAME";
}
}

@PostUpdate
private void afterUpdate() {
System.out.println("User updated with ID: " + this.id);
}
}


Жизненный цикл

@PreUpdate:
Вызывается перед выполнением операции update в EntityManager.
Используется для валидации или модификации данных перед обновлением.
Пример: проверка обязательных полей, обновление временных меток.


@PostUpdate:
Вызывается после успешного выполнения операции update и фиксации транзакции.
Используется для выполнения действий после обновления, например, логирования или отправки уведомлений.
Пример: логирование ID обновленной сущности, отправка события в систему сообщений.


Кастомизация событий:
Если требуется более сложная обработка событий, можно использовать @EntityListeners для определения слушателей сущностей.

Пример использования @EntityListeners:
@Entity
@EntityListeners(UserListener.class)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;
}

public class UserListener {
@PreUpdate
public void beforeUpdate(User user) {
System.out.println("Before updating user: " + user.getName());
}

@PostUpdate
public void afterUpdate(User user) {
System.out.println("User updated with ID: " + user.getId());
}
}


Варианты настройки

Использование в сущности:
Методы @PreUpdate и @PostUpdate можно определить непосредственно в сущности.

Использование @EntityListeners:
Для разделения логики можно вынести методы обратного вызова в отдельный класс и использовать @EntityListeners.

Глобальные слушатели:
Для применения логики ко всем сущностям можно зарегистрировать глобальный слушатель через Hibernate.

Пример глобального слушателя:
public class GlobalEntityListener {
@PreUpdate
public void beforeUpdate(Object entity) {
System.out.println("Before updating entity: " + entity.getClass().getSimpleName());
}

@PostUpdate
public void afterUpdate(Object entity) {
System.out.println("Entity updated: " + entity.getClass().getSimpleName());
}
}


Регистрация глобального слушателя в Hibernate:
spring.jpa.properties.hibernate.ejb.event.pre-update=com.example.GlobalEntityListener
spring.jpa.properties.hibernate.ejb.event.post-update=com.example.GlobalEntityListener


#Java #Training #Hard #Spring #SpringDataJPA #PreUpdate #PostUpdate
Аннотации @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.


Пример:
@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). Это гарантирует, что все ожидающие изменения будут синхронизированы с базой данных перед выполнением модифицирующего запроса.


Пример:
@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.

Пример:
@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), который должен использоваться для управления транзакцией. Если не указано, используется менеджер транзакций по умолчанию.


Пример:
@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:
@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. Если не указано, используется пакет, в котором находится класс с аннотацией.


Пример:
@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