👍1
Вопросы с собеседования 👩💻
Какой метод используется для очистки ArrayList?
Какой метод используется для очистки ArrayList?
Anonymous Quiz
2%
empty()
4%
reset()
60%
clear()
33%
removeAll()
👍2
@DynamicInsert в Hibernate
Аннотация @DynamicInsert (из пакета org.hibernate.annotations) указывает Hibernate генерировать SQL-запросы INSERT только для ненулевых полей сущности. Это позволяет оптимизировать вставку данных, исключая из запроса столбцы со значениями null.
Применяется на уровне класса сущности:
У @DynamicInsert нет настраиваемых атрибутов — это маркерная аннотация (присутствие/отсутствие влияет на поведение).
Как работает
Если @DynamicInsert = true (или аннотация присутствует):
Hibernate анализирует, какие поля сущности не null.
В SQL-запрос INSERT включаются только эти поля.
Если @DynamicInsert = false (по умолчанию):
В INSERT попадают все поля, включая null.
Примеры SQL
Без @DynamicInsert
Сгенерированный SQL (все поля, даже age=null):
С @DynamicInsert
Тот же код, но SQL будет короче:
Жизненный цикл и обработка
Во время компиляции маппинга
Hibernate определяет, нужно ли учитывать @DynamicInsert для сущности.
При выполнении session.save()
Проверяются значения полей.
Формируется SQL с учетом только ненулевых полей.
При генерации прокси-классов (если используется ленивая загрузка)
Не влияет напрямую, но может уменьшить объем данных в кеше.
Настройки и интеграция
В hibernate.cfg.xml или application.properties:
Но лучше использовать аннотацию для точечного контроля.
Совместимость с другими аннотациями
@DynamicUpdate – аналогично оптимизирует UPDATE.
@SelectBeforeUpdate – может конфликтовать (проверяет изменения перед UPDATE).
Когда использовать
Плюсы
Уменьшает размер SQL-запросов.
Ускоряет вставку, если много null-полей.
Полезно для таблиц с большим числом столбцов.
Минусы
Усложняет отладку (меняется SQL).
Незначительный оверхед на проверку null.
Бесполезен, если все поля обычно заполнены.
Оптимальные сценарии
Таблицы с 50+ столбцами, где большинство значений null.
Частые вставки частично заполненных объектов.
Работа с унаследованными системами, где NULL в столбцах нежелателен.
Примеры
Пример 1: Игнорирование null
При сохранении Product(id=1, name="Laptop", stock=null):
Комбинация с @ColumnDefault
При Account(id=1, balance=null) в БД запишется balance=0.
Ограничения
Не работает с @GeneratedValue (Hibernate требует все поля для идентификации).
Не влияет на JPQL/HQL – только на SQL, генерируемый Hibernate.
Проблемы с кешированием – если кеш второго уровня ожидает полный объект.
#Java #Training #Hard #Spring #Hibernate #DynamicInsert
Аннотация @DynamicInsert (из пакета org.hibernate.annotations) указывает Hibernate генерировать SQL-запросы INSERT только для ненулевых полей сущности. Это позволяет оптимизировать вставку данных, исключая из запроса столбцы со значениями null.
Применяется на уровне класса сущности:
@Entity
@DynamicInsert
public class User { ... }
У @DynamicInsert нет настраиваемых атрибутов — это маркерная аннотация (присутствие/отсутствие влияет на поведение).
Как работает
Если @DynamicInsert = true (или аннотация присутствует):
Hibernate анализирует, какие поля сущности не null.
В SQL-запрос INSERT включаются только эти поля.
Если @DynamicInsert = false (по умолчанию):
В INSERT попадают все поля, включая null.
Примеры SQL
Без @DynamicInsert
User user = new User();
user.setId(1L);
user.setName("Alice"); // age = null
Сгенерированный SQL (все поля, даже age=null):
INSERT INTO user (id, name, age) VALUES (1, 'Alice', NULL);
С @DynamicInsert
@DynamicInsert
@Entity
public class User { ... }
Тот же код, но SQL будет короче:
INSERT INTO user (id, name) VALUES (1, 'Alice'); -- поле age пропущено!
Жизненный цикл и обработка
Во время компиляции маппинга
Hibernate определяет, нужно ли учитывать @DynamicInsert для сущности.
При выполнении session.save()
Проверяются значения полей.
Формируется SQL с учетом только ненулевых полей.
При генерации прокси-классов (если используется ленивая загрузка)
Не влияет напрямую, но может уменьшить объем данных в кеше.
Настройки и интеграция
В hibernate.cfg.xml или application.properties:
hibernate.dynamic_insert=true # Применяется ко всем сущностям!
Но лучше использовать аннотацию для точечного контроля.
Совместимость с другими аннотациями
@DynamicUpdate – аналогично оптимизирует UPDATE.
@SelectBeforeUpdate – может конфликтовать (проверяет изменения перед UPDATE).
Когда использовать
Плюсы
Уменьшает размер SQL-запросов.
Ускоряет вставку, если много null-полей.
Полезно для таблиц с большим числом столбцов.
Минусы
Усложняет отладку (меняется SQL).
Незначительный оверхед на проверку null.
Бесполезен, если все поля обычно заполнены.
Оптимальные сценарии
Таблицы с 50+ столбцами, где большинство значений null.
Частые вставки частично заполненных объектов.
Работа с унаследованными системами, где NULL в столбцах нежелателен.
Примеры
Пример 1: Игнорирование null
@DynamicInsert
@Entity
public class Product {
@Id
private Long id;
private String name;
private Integer stock; // Часто null для новых товаров
}
При сохранении Product(id=1, name="Laptop", stock=null):
INSERT INTO product (id, name) VALUES (1, 'Laptop');
Комбинация с @ColumnDefault
@DynamicInsert
@Entity
public class Account {
@Id
private Long id;
@ColumnDefault("0")
private BigDecimal balance; // Если null, БД подставит 0
}
При Account(id=1, balance=null) в БД запишется balance=0.
Ограничения
Не работает с @GeneratedValue (Hibernate требует все поля для идентификации).
Не влияет на JPQL/HQL – только на SQL, генерируемый Hibernate.
Проблемы с кешированием – если кеш второго уровня ожидает полный объект.
#Java #Training #Hard #Spring #Hibernate #DynamicInsert
👍2
"Информация — это разрешение неопределенности."
Клод Шеннон, основатель теории информации, написал это в 1948 году в статье "A Mathematical Theory of Communication" для Bell System Technical Journal.
Почитать короткую биографию
Хабр
#Citation #Biography
Please open Telegram to view this post
VIEW IN TELEGRAM
Wikipedia
Claude Shannon
American mathematician and information theorist (1916–2001)
👍1
@DynamicUpdate в Hibernate
Аннотация @DynamicUpdate (из пакета org.hibernate.annotations) указывает Hibernate генерировать SQL-запросы UPDATE только для изменившихся полей сущности, а не для всех полей. Это улучшает производительность, особенно для таблиц с большим количеством столбцов.
Применяется на уровне класса сущности:
Как работает
Если @DynamicUpdate = true (или аннотация присутствует):
Hibernate отслеживает изменения в полях сущности.
В SQL-запрос UPDATE включаются только измененные поля.
Если @DynamicUpdate = false (по умолчанию):
В UPDATE попадают все поля, даже если их значения не изменились.
Примеры SQL
Без @DynamicUpdate
Сгенерированный SQL (все поля, даже неизмененные):
С @DynamicUpdate
Тот же код, но SQL будет короче:
Жизненный цикл и обработка
При загрузке сущности
Hibernate сохраняет исходные значения полей (снимок состояния).
При изменении полей
Сравниваются текущие значения с исходными.
При выполнении session.update() или transaction.commit()
Формируется SQL только для измененных полей.
Влияние на кеширование
Кеш второго уровня обновляется только фактически измененными данными.
Настройки и интеграция
В hibernate.cfg.xml или application.properties:
Но рекомендуется использовать аннотацию для точного контроля.
Совместимость с другими аннотациями
@DynamicInsert – аналогичная оптимизация для INSERT.
@SelectBeforeUpdate – если true, Hibernate сначала загружает текущее состояние, что увеличивает точность @DynamicUpdate.
Когда использовать
Плюсы
Уменьшает объем SQL-запросов.
Ускоряет UPDATE для "широких" таблиц.
Снижает нагрузку на БД.
Минусы
Небольшой оверхед на отслеживание изменений.
Может усложнить отладку (меняется SQL).
Оптимальные сценарии
Таблицы с 20+ столбцами, где обновляются 1-2 поля.
Частые обновления части полей (например, счетчики, статусы).
Системы с высокой нагрузкой на БД.
#Java #Training #Hard #Spring #Hibernate #DynamicUpdate
Аннотация @DynamicUpdate (из пакета org.hibernate.annotations) указывает Hibernate генерировать SQL-запросы UPDATE только для изменившихся полей сущности, а не для всех полей. Это улучшает производительность, особенно для таблиц с большим количеством столбцов.
Применяется на уровне класса сущности:
@Entity
@DynamicUpdate
public class User { ... }
Как работает
Если @DynamicUpdate = true (или аннотация присутствует):
Hibernate отслеживает изменения в полях сущности.
В SQL-запрос UPDATE включаются только измененные поля.
Если @DynamicUpdate = false (по умолчанию):
В UPDATE попадают все поля, даже если их значения не изменились.
Примеры SQL
Без @DynamicUpdate
User user = session.get(User.class, 1L);
user.setName("Alice"); // Меняем только имя
Сгенерированный SQL (все поля, даже неизмененные):
UPDATE user SET name='Alice', age=30, email='alice@example.com' WHERE id=1;
С @DynamicUpdate
@DynamicUpdate
@Entity
public class User { ... }
Тот же код, но SQL будет короче:
UPDATE user SET name='Alice' WHERE id=1; -- Только измененное поле!
Жизненный цикл и обработка
При загрузке сущности
Hibernate сохраняет исходные значения полей (снимок состояния).
При изменении полей
Сравниваются текущие значения с исходными.
При выполнении session.update() или transaction.commit()
Формируется SQL только для измененных полей.
Влияние на кеширование
Кеш второго уровня обновляется только фактически измененными данными.
Настройки и интеграция
В hibernate.cfg.xml или application.properties:
hibernate.dynamic_update=true # Применяется ко всем сущностям
Но рекомендуется использовать аннотацию для точного контроля.
Совместимость с другими аннотациями
@DynamicInsert – аналогичная оптимизация для INSERT.
@SelectBeforeUpdate – если true, Hibernate сначала загружает текущее состояние, что увеличивает точность @DynamicUpdate.
Когда использовать
Плюсы
Уменьшает объем SQL-запросов.
Ускоряет UPDATE для "широких" таблиц.
Снижает нагрузку на БД.
Минусы
Небольшой оверхед на отслеживание изменений.
Может усложнить отладку (меняется SQL).
Оптимальные сценарии
Таблицы с 20+ столбцами, где обновляются 1-2 поля.
Частые обновления части полей (например, счетчики, статусы).
Системы с высокой нагрузкой на БД.
#Java #Training #Hard #Spring #Hibernate #DynamicUpdate
👍2
Что выведет код?
#Tasks
import java.util.HashSet;
import java.util.Set;
public class Task090425 {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("A");
set.add(new String("A"));
set.add("B");
set.remove(new String("A"));
System.out.println(set.size());
}
}
#Tasks
👍1
👍1
Вопросы с собеседования 👩💻
Какой метод возвращает квадратный корень числа?
Какой метод возвращает квадратный корень числа?
Anonymous Quiz
8%
Math.power()
14%
Math.square()
74%
Math.sqrt()
4%
Math.root()
👍2
@Filter в Hibernate
Аннотация @Filter позволяет динамически применять условия фильтрации к сущностям или коллекциям на уровне базы данных. Она используется для ограничения выборки данных в зависимости от заданных параметров. Находится в пакете org.hibernate.annotations.
Параметры и настройки
Аннотация @Filter имеет следующие атрибуты:
name (обязательный, String):
Уникальное имя фильтра, которое используется для его активации/деактивации в сессии.
Пример: @Filter(name = "activeUserFilter").
condition (необязательный, String):
SQL-условие, которое добавляется в запрос при активации фильтра.
Может содержать параметры (например, :param), которые задаются во время выполнения.
Пример: @Filter(name = "activeUserFilter", condition = "is_active = :activeStatus").
deduceAliasInjectionPoints (необязательный, boolean, default = true):
Определяет, должен ли Hibernate автоматически подставлять алиасы таблиц в условие.
Если false, условие должно содержать явные алиасы.
Жизненный цикл фильтра
Объявление фильтра:
Фильтр определяется на уровне класса сущности (@Entity) или коллекции (@ElementCollection, @OneToMany и др.).
Пример:
Активация фильтра в сессии:
Фильтр не активен по умолчанию, его нужно включать явно в Session или EntityManager.
Пример:
Применение в запросах:
После активации фильтр автоматически добавляет условие ко всем запросам, связанным с сущностью.
Для @OneToMany и других коллекций фильтр применяется при загрузке ассоциаций.
Деактивация фильтра:
Фильтр можно отключить:
Механизмы Hibernate и Spring, связанные с @Filter
1. @FilterDef и @ParamDef
@FilterDef определяет фильтр и его параметры.
@ParamDef задает тип параметра (например, String, boolean).
Должен быть указан на уровне класса (обычно на @Entity или в package-info.java).
2. Интеграция с Spring Data JPA
Фильтры можно активировать в Spring-репозиториях через EntityManager:
3. Глобальная настройка фильтров в Spring Boot
Можно автоматически включать фильтры для всех запросов через @PostConstruct:
Варианты настройки и применения
1. Фильтрация коллекций
2. Множественные фильтры
3. Динамическое управление фильтрами
#Java #Training #Hard #Spring #Hibernate #Filter #FilterDef
Аннотация @Filter позволяет динамически применять условия фильтрации к сущностям или коллекциям на уровне базы данных. Она используется для ограничения выборки данных в зависимости от заданных параметров. Находится в пакете org.hibernate.annotations.
Параметры и настройки
Аннотация @Filter имеет следующие атрибуты:
name (обязательный, String):
Уникальное имя фильтра, которое используется для его активации/деактивации в сессии.
Пример: @Filter(name = "activeUserFilter").
condition (необязательный, String):
SQL-условие, которое добавляется в запрос при активации фильтра.
Может содержать параметры (например, :param), которые задаются во время выполнения.
Пример: @Filter(name = "activeUserFilter", condition = "is_active = :activeStatus").
deduceAliasInjectionPoints (необязательный, boolean, default = true):
Определяет, должен ли Hibernate автоматически подставлять алиасы таблиц в условие.
Если false, условие должно содержать явные алиасы.
Жизненный цикл фильтра
Объявление фильтра:
Фильтр определяется на уровне класса сущности (@Entity) или коллекции (@ElementCollection, @OneToMany и др.).
Пример:
@Entity
@FilterDef(name = "activeUserFilter",
condition = "is_active = :activeStatus",
parameters = @ParamDef(name = "activeStatus", type = boolean.class))
@Filter(name = "activeUserFilter")
public class User { ... }
Активация фильтра в сессии:
Фильтр не активен по умолчанию, его нужно включать явно в Session или EntityManager.
Пример:
session.enableFilter("activeUserFilter")
.setParameter("activeStatus", true);
Применение в запросах:
После активации фильтр автоматически добавляет условие ко всем запросам, связанным с сущностью.
Для @OneToMany и других коллекций фильтр применяется при загрузке ассоциаций.
Деактивация фильтра:
Фильтр можно отключить:
session.disableFilter("activeUserFilter");
Механизмы Hibernate и Spring, связанные с @Filter
1. @FilterDef и @ParamDef
@FilterDef определяет фильтр и его параметры.
@ParamDef задает тип параметра (например, String, boolean).
Должен быть указан на уровне класса (обычно на @Entity или в package-info.java).
2. Интеграция с Spring Data JPA
Фильтры можно активировать в Spring-репозиториях через EntityManager:
@Repository
public class UserRepository {
@PersistenceContext
private EntityManager em;
public List<User> findActiveUsers() {
em.unwrap(Session.class)
.enableFilter("activeUserFilter")
.setParameter("activeStatus", true);
return em.createQuery("FROM User", User.class).getResultList();
}
}
3. Глобальная настройка фильтров в Spring Boot
Можно автоматически включать фильтры для всех запросов через @PostConstruct:
@Component
public class HibernateFilterConfig {
@PersistenceContext
private EntityManager em;
@PostConstruct
public void init() {
Session session = em.unwrap(Session.class);
session.enableFilter("activeUserFilter")
.setParameter("activeStatus", true);
}
}
Варианты настройки и применения
1. Фильтрация коллекций
@Entity
public class Department {
@OneToMany(mappedBy = "department")
@Filter(name = "activeUserFilter", condition = "is_active = :activeStatus")
private List<User> users;
}
2. Множественные фильтры
@Entity
@FilterDef(name = "activeFilter", condition = "is_active = :active")
@FilterDef(name = "roleFilter", condition = "role = :roleName")
@Filter(name = "activeFilter")
@Filter(name = "roleFilter")
public class User { ... }
3. Динамическое управление фильтрами
// Включение разных параметров в runtime
session.enableFilter("activeUserFilter")
.setParameter("activeStatus", true);
session.enableFilter("roleFilter")
.setParameter("roleName", "ADMIN");
#Java #Training #Hard #Spring #Hibernate #Filter #FilterDef
👍3
"Разработчики, разработчики, разработчики!"
Стив Балмер, бывший CEO Microsoft, выкрикнул это в 2000 году на конференции разработчиков в Редмонде, подчеркивая их важность для компании.
https://rutube.ru/video/2030e89f49d5a5ed1b48f5706bf0b49e/
Почитать короткую биографию
#Citation #Biography
Please open Telegram to view this post
VIEW IN TELEGRAM
RUTUBE
Steve Ballmer: Developers, developers, developers
Вспомним зажигательного Стива:
"Достаточно вспомнить 2008 год, когда на конференции разработчиков эксцентричный руководитель Microsoft 14 раз прокричал слово «Developers», будто это заклинание."
«Нет никаких шансов, что iPhone получит сколь либо значительную…
"Достаточно вспомнить 2008 год, когда на конференции разработчиков эксцентричный руководитель Microsoft 14 раз прокричал слово «Developers», будто это заклинание."
«Нет никаких шансов, что iPhone получит сколь либо значительную…
👍1
@Formula в Hibernate
Аннотация @Formula позволяет задавать вычисляемые (производные) поля в сущностях Hibernate, значения которых не хранятся в базе данных, а вычисляются на основе SQL-выражения. Находится в пакете org.hibernate.annotations.
Атрибуты аннотации
value (String, обязательный):
SQL-выражение, которое выполняется при загрузке сущности из БД.
Может включать столбцы таблицы, агрегатные функции (SUM, AVG), подзапросы и даже вызовы SQL-функций.
Пример:
Жизненный цикл
Загрузка сущности:
При выборке сущности из БД (EntityManager.find(), HQL, Criteria API) Hibernate выполняет SQL из @Formula и подставляет результат в поле.
Вычисление происходит на стороне БД, а не в Java-коде.
Обновление сущности:
Поле, помеченное @Formula, не сохраняется в БД при INSERT/UPDATE.
Если SQL-выражение зависит от других полей, его значение пересчитывается при каждой загрузке.
Кэширование:
Если сущность кэшируется (например, через @Cacheable), значение @Formula также кэшируется.
Обработка @Formula
Во время компиляции Hibernate:
Hibernate парсит SQL-выражение и проверяет его синтаксис (но не валидирует до выполнения запроса).
Если выражение содержит ссылки на другие таблицы, Hibernate не создает JOIN автоматически – нужно явно указывать подзапросы.
В рантайме:
При генерации SQL для загрузки сущности Hibernate подставляет формулу как есть (без параметризации).
Зависимость от диалекта БД
Поскольку @Formula использует "сырой" SQL, выражение должно быть совместимо с диалектом Hibernate (MySQLDialect, PostgreSQLDialect и т. д.).
Пример для PostgreSQL:
Варианты использования и ограничения
1. Динамические вычисления
Расчет рейтинга на основе связанных данных:
2. Использование SQL-функций
Форматирование даты:
3. Ограничения
Нет поддержки JPA-стандарта: @Formula – это аннотация Hibernate, а не JPA.
Нет параметризации: SQL в @Formula статичен, нельзя передавать параметры.
Производительность: Сложные подзапросы могут замедлять загрузку сущностей.
Альтернативы
@PostLoad + вычисление в Java:
Плюс: независимость от SQL. Минус: вычисление в Java, а не в БД.
Представления (Database Views) + @Immutable:
Создать VIEW в БД и отобразить его как неизменяемую сущность.
#Java #Training #Hard #Spring #Hibernate #Formula
Аннотация @Formula позволяет задавать вычисляемые (производные) поля в сущностях Hibernate, значения которых не хранятся в базе данных, а вычисляются на основе SQL-выражения. Находится в пакете org.hibernate.annotations.
Атрибуты аннотации
value (String, обязательный):
SQL-выражение, которое выполняется при загрузке сущности из БД.
Может включать столбцы таблицы, агрегатные функции (SUM, AVG), подзапросы и даже вызовы SQL-функций.
Пример:
@Formula("(SELECT COUNT(*) FROM orders o WHERE o.customer_id = id)")
private int orderCount;
Жизненный цикл
Загрузка сущности:
При выборке сущности из БД (EntityManager.find(), HQL, Criteria API) Hibernate выполняет SQL из @Formula и подставляет результат в поле.
Вычисление происходит на стороне БД, а не в Java-коде.
Обновление сущности:
Поле, помеченное @Formula, не сохраняется в БД при INSERT/UPDATE.
Если SQL-выражение зависит от других полей, его значение пересчитывается при каждой загрузке.
Кэширование:
Если сущность кэшируется (например, через @Cacheable), значение @Formula также кэшируется.
Обработка @Formula
Во время компиляции Hibernate:
Hibernate парсит SQL-выражение и проверяет его синтаксис (но не валидирует до выполнения запроса).
Если выражение содержит ссылки на другие таблицы, Hibernate не создает JOIN автоматически – нужно явно указывать подзапросы.
В рантайме:
При генерации SQL для загрузки сущности Hibernate подставляет формулу как есть (без параметризации).
Зависимость от диалекта БД
Поскольку @Formula использует "сырой" SQL, выражение должно быть совместимо с диалектом Hibernate (MySQLDialect, PostgreSQLDialect и т. д.).
Пример для PostgreSQL:
@Formula("CONCAT(first_name, ' ', last_name)")
private String fullName;
Для MySQL CONCAT работает аналогично, но в Oracle нужно использовать ||.
Варианты использования и ограничения
1. Динамические вычисления
Расчет рейтинга на основе связанных данных:
@Formula("(SELECT AVG(r.rating) FROM reviews r WHERE r.product_id = id)")
private Double averageRating;
2. Использование SQL-функций
Форматирование даты:
@Formula("TO_CHAR(created_at, 'YYYY-MM-DD')")
private String creationDate;
3. Ограничения
Нет поддержки JPA-стандарта: @Formula – это аннотация Hibernate, а не JPA.
Нет параметризации: SQL в @Formula статичен, нельзя передавать параметры.
Производительность: Сложные подзапросы могут замедлять загрузку сущностей.
Альтернативы
@PostLoad + вычисление в Java:
@Transient
private int orderCount;
@PostLoad
private void calculateOrderCount() {
this.orderCount = orderRepository.countByCustomerId(this.id);
}
Плюс: независимость от SQL. Минус: вычисление в Java, а не в БД.
Представления (Database Views) + @Immutable:
Создать VIEW в БД и отобразить его как неизменяемую сущность.
#Java #Training #Hard #Spring #Hibernate #Formula
👌2👍1
Что выведет код?
#Tasks
import java.util.HashSet;
import java.util.Set;
class Person1004 {
String name;
Person1004(String name) { this.name = name; }
public boolean equals(Object o) {
return this.name.length() == ((Person1004)o).name.length();
}
}
public class Task100425 {
public static void main(String[] args) {
Set<Person1004> set = new HashSet<>();
set.add(new Person1004("Alice"));
set.add(new Person1004("Bob"));
set.add(new Person1004("Charlie"));
set.add(new Person1004("Dave"));
System.out.println(set.size());
}
}
#Tasks
👍1
👍1
Вопросы с собеседования 👩💻
Что такое default метод в интерфейсе?
Что такое default метод в интерфейсе?
Anonymous Quiz
13%
Метод без реализации
87%
Метод с реализацией по умолчанию
0%
Приватный метод
0%
Статический метод
👍1
@Generated в Hibernate
Аннотация @Generated указывает, что значение поля автоматически генерируется базой данных (например, через DEFAULT, TRIGGER, AUTO_INCREMENT или вычисляемый столбец). В отличие от @Formula, поле сохраняется в БД, но Hibernate обновляет его после вставки или обновления. Находится в пакете org.hibernate.annotations.
Атрибуты аннотации
GenerationTime (обязательный):
Определяет, когда значение генерируется:
GenerationTime.INSERT – только при вставке (например, AUTO_INCREMENT).
GenerationTime.ALWAYS – при вставке и обновлении (например, триггеры или DEFAULT-значения).
value (необязательный, String):
SQL-выражение, которое генерирует значение (если БД поддерживает, например, DEFAULT CURRENT_TIMESTAMP).
Используется редко, так как обычно генерация определяется на стороне БД.
Жизненный цикл
При сохранении (INSERT)
Если GenerationTime.INSERT или GenerationTime.ALWAYS:
Hibernate выполняет INSERT, пропуская это поле.
После вставки делает SELECT (или использует RETURNING в PostgreSQL), чтобы получить сгенерированное значение.
Пример для AUTO_INCREMENT:
При обновлении (UPDATE)
Если GenerationTime.ALWAYS:
Hibernate пропускает поле в UPDATE.
После обновления делает SELECT для получения нового значения.
Пример для триггера, обновляющего last_modified:
Кэширование
Если включен кэш второго уровня (@Cacheable), Hibernate обновляет значение в кэше после SELECT.
Механизмы Hibernate и настройки
1. Как Hibernate обрабатывает @Generated
Генерация SQL:
Поле исключается из INSERT/UPDATE.
Для получения значения выполняется дополнительный SELECT (если БД не поддерживает RETURNING).
Поддержка RETURNING (PostgreSQL, Oracle, SQL Server):
Если диалект поддерживает RETURNING, Hibernate использует его вместо отдельного SELECT:
2. Зависимость от диалекта БД
Поведение зависит от возможностей БД:
MySQL: AUTO_INCREMENT, DEFAULT CURRENT_TIMESTAMP.
PostgreSQL: SERIAL, GENERATED ALWAYS AS IDENTITY, триггеры.
Oracle: SEQUENCE + триггеры, DEFAULT-значения.
Примеры использования
1. Автоинкрементный ID
Эквивалент Hibernate:
2. Временная метка создания
3. Триггер для аудита
Ограничения и альтернативы
Ограничения:
Не все БД поддерживают RETURNING:
Для MySQL требуется дополнительный SELECT.
Нет контроля над генерацией:
Логика полностью определяется БД (триггеры, DEFAULT).
Альтернативы:
@PrePersist и @PreUpdate (JPA):
#Java #Training #Hard #Spring #Hibernate #Generated
Аннотация @Generated указывает, что значение поля автоматически генерируется базой данных (например, через DEFAULT, TRIGGER, AUTO_INCREMENT или вычисляемый столбец). В отличие от @Formula, поле сохраняется в БД, но Hibernate обновляет его после вставки или обновления. Находится в пакете org.hibernate.annotations.
Атрибуты аннотации
GenerationTime (обязательный):
Определяет, когда значение генерируется:
GenerationTime.INSERT – только при вставке (например, AUTO_INCREMENT).
GenerationTime.ALWAYS – при вставке и обновлении (например, триггеры или DEFAULT-значения).
value (необязательный, String):
SQL-выражение, которое генерирует значение (если БД поддерживает, например, DEFAULT CURRENT_TIMESTAMP).
Используется редко, так как обычно генерация определяется на стороне БД.
Жизненный цикл
При сохранении (INSERT)
Если GenerationTime.INSERT или GenerationTime.ALWAYS:
Hibernate выполняет INSERT, пропуская это поле.
После вставки делает SELECT (или использует RETURNING в PostgreSQL), чтобы получить сгенерированное значение.
Пример для AUTO_INCREMENT:
INSERT INTO users (name) VALUES ('Alice'); -- id не указывается
SELECT last_insert_id(); -- Hibernate получает сгенерированный ID
При обновлении (UPDATE)
Если GenerationTime.ALWAYS:
Hibernate пропускает поле в UPDATE.
После обновления делает SELECT для получения нового значения.
Пример для триггера, обновляющего last_modified:
UPDATE users SET name = 'Bob' WHERE id = 1; -- last_modified не указывается
SELECT last_modified FROM users WHERE id = 1; -- Hibernate получает новое значение
Кэширование
Если включен кэш второго уровня (@Cacheable), Hibernate обновляет значение в кэше после SELECT.
Механизмы Hibernate и настройки
1. Как Hibernate обрабатывает @Generated
Генерация SQL:
Поле исключается из INSERT/UPDATE.
Для получения значения выполняется дополнительный SELECT (если БД не поддерживает RETURNING).
Поддержка RETURNING (PostgreSQL, Oracle, SQL Server):
Если диалект поддерживает RETURNING, Hibernate использует его вместо отдельного SELECT:
INSERT INTO users (name) VALUES ('Alice') RETURNING id, created_at;
2. Зависимость от диалекта БД
Поведение зависит от возможностей БД:
MySQL: AUTO_INCREMENT, DEFAULT CURRENT_TIMESTAMP.
PostgreSQL: SERIAL, GENERATED ALWAYS AS IDENTITY, триггеры.
Oracle: SEQUENCE + триггеры, DEFAULT-значения.
Примеры использования
1. Автоинкрементный ID
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // Аналог для JPA
private Long id;
Эквивалент Hibernate:
@Id
@Generated(GenerationTime.INSERT)
private Long id;
2. Временная метка создания
@Column(insertable = false) // Не указывается в INSERT
@Generated(GenerationTime.INSERT)
private LocalDateTime createdAt; // DEFAULT CURRENT_TIMESTAMP в БД
3. Триггер для аудита
@Column(updatable = false)
@Generated(GenerationTime.ALWAYS)
private LocalDateTime lastModified; // Обновляется триггером БД
Ограничения и альтернативы
Ограничения:
Не все БД поддерживают RETURNING:
Для MySQL требуется дополнительный SELECT.
Нет контроля над генерацией:
Логика полностью определяется БД (триггеры, DEFAULT).
Альтернативы:
@PrePersist и @PreUpdate (JPA):
@PrePersist
private void prePersist() {
this.createdAt = LocalDateTime.now();
}
Плюс: работает везде. Минус: значение генерируется в Java, а не в БД.
#Java #Training #Hard #Spring #Hibernate #Generated
👍3