@OnDelete в Hibernate
Аннотация @OnDelete определяет действие при удалении связанной сущности на уровне базы данных (через ON DELETE CASCADE или ON DELETE SET NULL). Это DDL-инструкция, а не логика Hibernate.
Пакет: org.hibernate.annotations
Применяется к: ассоциациям (@OneToOne, @ManyToOne, @OneToMany).
Влияние: Генерирует соответствующий SQL-констрейнт в БД.
Параметры и настройки
action: Варианты: CASCADE (удалить зависимые записи) или SET_NULL (обнулить ссылку).
Примеры
Жизненный цикл и обработка
Как работает @OnDelete?
При генерации DDL:
Hibernate добавляет в SQL-скрипт ON DELETE CASCADE/SET NULL для внешнего ключа.
При удалении через БД:
Если запись удаляется напрямую SQL (минуя Hibernate), констрейнт срабатывает автоматически.
При удалении через Hibernate:
Если action = CASCADE, Hibernate сначала удаляет дочерние сущности (если нет orphanRemoval).
Ограничения
Не влияет на логику EntityManager.remove().
Не работает с @ManyToMany (только через @JoinTable + отдельные констрейнты).
Примеры использования
Пример 1: Каскадное удаление (CASCADE)
Пример 2: Обнуление ссылки (SET_NULL)
Проблемы
Неявное удаление: При CASCADE данные могут исчезнуть без явного вызова delete().
Несовместимость: Некоторые БД (например, MySQL с InnoDB) требуют индексов для ON DELETE CASCADE.
Когда использовать?
Для жестких зависимостей (например, Order → User).
В legacy-системах, где удаление управляется триггерами БД.
#Java #Training #Hard #Spring #Hibernate #OnDelete
Аннотация @OnDelete определяет действие при удалении связанной сущности на уровне базы данных (через ON DELETE CASCADE или ON DELETE SET NULL). Это DDL-инструкция, а не логика Hibernate.
Пакет: org.hibernate.annotations
Применяется к: ассоциациям (@OneToOne, @ManyToOne, @OneToMany).
Влияние: Генерирует соответствующий SQL-констрейнт в БД.
Параметры и настройки
action: Варианты: CASCADE (удалить зависимые записи) или SET_NULL (обнулить ссылку).
Примеры
@Entity
public class Order {
@ManyToOne
@OnDelete(action = OnDeleteAction.CASCADE) // При удалении User удалятся его Order
private User user;
}
Жизненный цикл и обработка
Как работает @OnDelete?
При генерации DDL:
Hibernate добавляет в SQL-скрипт ON DELETE CASCADE/SET NULL для внешнего ключа.
При удалении через БД:
Если запись удаляется напрямую SQL (минуя Hibernate), констрейнт срабатывает автоматически.
При удалении через Hibernate:
Если action = CASCADE, Hibernate сначала удаляет дочерние сущности (если нет orphanRemoval).
Ограничения
Не влияет на логику EntityManager.remove().
Не работает с @ManyToMany (только через @JoinTable + отдельные констрейнты).
Примеры использования
Пример 1: Каскадное удаление (CASCADE)
@Entity
public class Comment {
@ManyToOne
@OnDelete(action = OnDeleteAction.CASCADE) // Удалить комментарии при удалении Post
private Post post;
}
Пример 2: Обнуление ссылки (SET_NULL)
@Entity
public class Employee {
@ManyToOne
@OnDelete(action = OnDeleteAction.SET_NULL) // department_id = NULL при удалении Department
private Department department;
}
Проблемы
Неявное удаление: При CASCADE данные могут исчезнуть без явного вызова delete().
Несовместимость: Некоторые БД (например, MySQL с InnoDB) требуют индексов для ON DELETE CASCADE.
Когда использовать?
Для жестких зависимостей (например, Order → User).
В legacy-системах, где удаление управляется триггерами БД.
#Java #Training #Hard #Spring #Hibernate #OnDelete
👍2
@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).
Примеры
Жизненный цикл и обработка
Как работает оптимистичная блокировка?
При чтении сущности:
Hibernate запоминает состояние полей (для ALL/DIRTY).
При обновлении:
Генерируется SQL вида:
Если условие не выполняется (данные изменились), выбрасывается OptimisticLockException.
Интеграция с Spring Boot
Глобальная стратегия:
Обработка исключений:
Примеры использования
Пример 1: Проверка всех полей
Пример 2: Исключение поля
Проблемы
ALL/DIRTY: Требуют хранения исходного состояния (память).
Нет поддержки в JPA: Только Hibernate.
Когда использовать?
VERSION — для большинства случаев.
DIRTY — для больших сущностей с редкими конфликтами.
#Java #Training #Hard #Spring #Hibernate #OptimisticLock
Аннотация @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
👍2