Ответ
Hibernate — это ORM, который управляет жизненным циклом сущностей, преобразуя операции с объектами в SQL. Ключевые внутренние механизмы:
1. Сессия (Session) / EntityManager
Это контекст персистентности, кэш первого уровня. Все сущности, загруженные или сохраненные в рамках одной сессии, отслеживаются на предмет изменений (dirty checking).
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
User user = session.get(User.class, 1L); // Загружено в кэш сессии
user.setName("New Name"); // Изменение отслеживается
// При коммите Hibernate генерирует UPDATE только для измененных полей
tx.commit();
session.close();
2. Ленивая загрузка (Lazy Loading)
Связи (@OneToMany, @ManyToOne) по умолчанию загружаются лениво через прокси-объекты. Запрос к полю инициирует реальный SQL.
@Entity
public class User {
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Order> orders; // Прокси, а не реальный список
}
User user = session.get(User.class, 1L);
// SQL SELECT * FROM orders WHERE user_id = 1 выполнится здесь:
List<Order> orders = user.getOrders();
3. Кэширование
- Кэш 1-го уровня (сессия): Кратковременный, привязан к сессии. Гарантирует, что в рамках одной транзакции будет один объект на запись в БД.
- Кэш 2-го уровня (приложение): Разделяемый между сессиями (например, Ehcache, Infinispan). Требует явной настройки и аннотации
@Cacheableна сущности.
4. Генерация SQL
Включите логирование для анализа:
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.use_sql_comments=true
Hibernate генерирует SQL, оптимизируя запросы (например, пакетная вставка при hibernate.jdbc.batch_size).
Проблемы и решения:
- N+1 проблема: Решается через
JOIN FETCHв HQL или@EntityGraph. - Утечка памяти: Всегда закрывайте сессии (используйте
try-with-resourcesили контекст управления транзакциями).