Рубрики
Без рубрики

Анти-шаблон hibernate.enable_lazy_load_no_trans

Автор оригинала: Vlad Mihalcea.

Я уже писал об антишаблоне OpenSessionInView , так что теперь пришло время добавить еще одну гибернацию, извлекающую плохие практики. Хотя свойство конфигурации hibernate.enable_lazy_load_no_trans является менее известным параметром, полезно знать, почему его не следует использовать в коде уровня доступа к данным.

По умолчанию это свойство отключено, и для его включения необходимо указать следующее свойство конфигурации:


Учитывая следующие сущности:

При наличии этого свойства конфигурации следующие фрагменты кода могут быть выполнены без исключения LazyInitializationException :

List comments = null;

EntityManager entityManager = null;
EntityTransaction transaction = null;
try {
    entityManager = entityManagerFactory()
        .createEntityManager();
    transaction = entityManager.getTransaction();
    transaction.begin();

    comments = entityManager.createQuery(
        "select pc " +
        "from PostComment pc " +
        "where pc.review = :review", PostComment.class)
    .setParameter("review", review)
    .getResultList();

    transaction.commit();
} catch (Throwable e) {
    if ( transaction != null && transaction.isActive())
        transaction.rollback();
    throw e;
} finally {
    if (entityManager != null) {
        entityManager.close();
    }
}
for(PostComment comment : comments) {
    LOGGER.info("The post title is '{}'", 
        comment.getPost().getTitle());
}

Без свойства конфигурации hibernate.enable_lazy_load_no_trans строка comment.getPost().getTitle() вызовет исключение LazyInitializationException , поскольку коллекция комментариев не была инициализирована, а контекст сохранения уже закрыт вместе с подключением к базе данных, которое извлекло сущность post .

За кулисами открывается временная Сессия только для инициализации каждой записи ассоциации. Каждый временный Сеанс подразумевает получение нового подключения к базе данных, а также новой транзакции базы данных.

Чем больше ассоциаций загружается лениво, тем больше дополнительных соединений будет запрошено, что оказывает давление на базовый пул соединений. Каждая ассоциация загружается в новую транзакцию, журнал транзакций вынужден очищаться после каждой инициализации ассоциации.

Как и OpenSessionInView , свойство конфигурации hibernate.enable_lazy_load_no_trans также является анти-шаблоном, поскольку оно лечит только симптомы и не устраняет фактическую причину исключения LazyInitializationException .

Путем правильной инициализации всех ленивых ассоциаций перед закрытием начального контекста сохранения и переключением D НА проекции , где сущности даже не нужны, исключение LazyInitializationException предотвращается гораздо более эффективным способом.