senior
Batch-операции в Hibernate
Batch-операции позволяют выполнять массовые INSERT/UPDATE/DELETE эффективно, группируя SQL-запросы в пакеты вместо отправки по одному.
Настройка batch insert/update
Пример
# application.properties
spring.jpa.properties.hibernate.jdbc.batch_size=50
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true
spring.jpa.properties.hibernate.jdbc.batch_versioned_data=true
Batch INSERT
Пример
@Transactional
public void batchInsert(List<User> users) {
for (int i = 0; i < users.size(); i++) {
entityManager.persist(users.get(i));
if (i % 50 == 0) { // batch_size = 50
entityManager.flush(); // отправить SQL в БД
entityManager.clear(); // очистить L1 Cache (освободить память)
}
}
}
IDENTITY vs SEQUENCE для batch
Пример
// IDENTITY — batch insert НЕВОЗМОЖЕН!
// Hibernate выполняет INSERT сразу для получения ID
@GeneratedValue(strategy = GenerationType.IDENTITY) // не подходит для batch
// SEQUENCE — batch insert РАБОТАЕТ
// Hibernate заранее получает блок ID из sequence
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "user_seq")
@SequenceGenerator(name = "user_seq", allocationSize = 50) // подходит для batch
Bulk UPDATE/DELETE (JPQL — обходит Persistence Context)
Пример
@Modifying
@Query("UPDATE User u SET u.status = :status WHERE u.lastLogin < :date")
int deactivateInactiveUsers(@Param("status") UserStatus status,
@Param("date") LocalDateTime date);
// Один SQL UPDATE, без загрузки сущностей
// ВАЖНО: @Modifying(clearAutomatically = true) — очистить L1 Cache после
Важное
- batch_size — количество SQL-операций, группируемых в один batch
order_inserts/order_updates— обязательно для эффективного batch (группировка по таблицам)flush() + clear()каждые N записей — предотвращение OutOfMemoryError при больших batch- SEQUENCE стратегия генерации ID — обязательна для batch INSERT (IDENTITY не поддерживает batch)
Частые ошибки
- IDENTITY + batch — Hibernate выполняет INSERT по одному; batch не работает
- Не вызывать
clear()— L1 Cache растёт с каждой persist(), 1M сущностей → OOM - Bulk UPDATE без
clearAutomatically— L1 Cache содержит устаревшие данные, следующийfind()вернёт старое значение - Не включить order_inserts — без сортировки Hibernate перемешивает INSERT разных таблиц, batch не формируется
Как используется в 2026
- Для массовых операций (импорт данных, миграции) — JDBC batch напрямую (через JdbcTemplate) или jOOQ
- Hibernate batch — для умеренных объёмов (тысячи, не миллионы)
- Spring Batch — для ETL-задач с миллионами записей
@ModifyingJPQL — для bulk UPDATE/DELETE; самый простой способ массового обновления
На собеседовании: ключевые моменты: batch_size + order_inserts + SEQUENCE (не IDENTITY!). Объясните, почему IDENTITY блокирует batch insert (Hibernate должен выполнить INSERT сразу для получения ID). Упомяните flush/clear паттерн для предотвращения OOM. Для миллионов записей — JDBC напрямую или Spring Batch.