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

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

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
@TableGenerator в JPA

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

Пакет: javax.persistence (JPA)

Применяется к: полю с @Id и
@GeneratedValue(strategy = GenerationType.TABLE).

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

Основные атрибуты
name: Уникальное имя генератора (обязательно).
table: Специальный объект для хранения значений (по умолчанию hibernate_sequences).
pkColumnName: Столбец, хранящий имена генераторов (по умолчанию sequence_name).
valueColumnName: Столбец, хранящий текущее значение (по умолчанию next_val).
pkColumnValue: Имя текущего генератора в pkColumnName (по умолчанию имя сущности).
initialValue: Начальное значение (по умолчанию 0).
allocationSize: Размер выделяемого блока значений (по умолчанию 50).
catalog: Каталог в БД (опционально).
schema: Схема в БД (опционально).
uniqueConstraints: Ограничения уникальности (опционально).


Жизненный цикл и обработка

Как работает генерация ID?
При старте приложения:
Если специльный объект не существует, Hibernate создает его автоматически (если ddl-auto=create или update).

При сохранении новой сущности:

Hibernate запрашивает новый диапазон значений (размером allocationSize).
Значения выделяются пакетно, что уменьшает количество обращений к БД.


При исчерпании диапазона:
Hibernate автоматически запрашивает следующий блок.

Пример SQL-запроса
SELECT next_val FROM hibernate_sequences WHERE sequence_name = 'employee_seq' FOR UPDATE;
UPDATE hibernate_sequences SET next_val = next_val + 50 WHERE sequence_name = 'employee_seq';


Интеграция с Spring Boot

Автогенерация схемы:
spring.jpa.hibernate.ddl-auto=update  


Кастомизация имени объекта:
@TableGenerator(  
name = "book_seq",
table = "custom_sequences",
pkColumnName = "seq_name",
valueColumnName = "seq_value",
allocationSize = 30
)


Примеры использования

Пример 1: Базовая настройка
@Entity  
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "emp_seq")
@TableGenerator(
name = "emp_seq",
allocationSize = 20
)
private Long id;
}


Пример 2: Кастомизация схемы
@TableGenerator(  
name = "project_seq",
schema = "hr",
table = "project_sequences",
initialValue = 1000
)


Проблемы

Производительность: Частые запросы к БД при малом allocationSize.
Блокировки: Использует SELECT ... FOR UPDATE, что может вызвать конкуренцию.


Когда использовать?

Когда не поддерживаются SEQUENCE (например, MySQL до 8.0).
Для переносимости между разными СУБД.



#Java #Training #Hard #Spring #JPA #TableGenerator
@OptimisticLock в Hibernate

Аннотация @OptimisticLock управляет оптимистичной блокировкой сущности в Hibernate, определяя, какие поля должны проверяться на изменение при обновлении.

Пакет: org.hibernate.annotations

Применяется к: классу сущности (@Entity) или отдельным полям.

Стратегии:
OptimisticLockType.VERSION (по умолчанию) — использует @Version.
OptimisticLockType.ALL — проверяет все поля.
OptimisticLockType.DIRTY — проверяет только измененные поля.
OptimisticLockType.NONE — отключает проверку.


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

Атрибуты
type: Стратегия проверки изменений (VERSION, ALL, DIRTY, NONE).
excluded: Если true, поле исключается из проверки (при type = ALL/DIRTY).


Примеры
@Entity  
@OptimisticLock(type = OptimisticLockType.ALL)
public class Account {
@Id
private Long id;

@OptimisticLock(excluded = true) // Не проверяется при обновлении
private String secretCode;
}


Жизненный цикл и обработка

Как работает оптимистичная блокировка?
При чтении сущности:
Hibernate запоминает состояние полей (для ALL/DIRTY).

При обновлении:
Генерируется SQL вида:
UPDATE account SET ... WHERE id = ? AND (secretCode IS NULL OR secretCode = ?)  


Если условие не выполняется (данные изменились), выбрасывается OptimisticLockException.

Интеграция с Spring Boot

Глобальная стратегия:
spring.jpa.properties.hibernate.optimistic_lock.strategy=all  


Обработка исключений:
@ExceptionHandler(OptimisticLockException.class)  
public void handleConflict() { /* ... */ }


Примеры использования

Пример 1: Проверка всех полей
@Entity  
@OptimisticLock(type = OptimisticLockType.ALL)
public class Product {
@Version
private Long version; // Дополнительная проверка
}


Пример 2: Исключение поля
@Entity  
@OptimisticLock(type = OptimisticLockType.DIRTY)
public class User {
@OptimisticLock(excluded = true)
private LocalDateTime lastLogin;
}


Проблемы

ALL/DIRTY: Требуют хранения исходного состояния (память).
Нет поддержки в JPA: Только Hibernate.


Когда использовать?

VERSION — для большинства случаев.
DIRTY — для больших сущностей с редкими конфликтами.


#Java #Training #Hard #Spring #Hibernate #OptimisticLock