Автор оригинала: Vlad Mihalcea.
Я уже писал об антишаблоне OpenSessionInView , так что теперь пришло время добавить еще одну гибернацию, извлекающую плохие практики. Хотя свойство конфигурации hibernate.enable_lazy_load_no_trans
является менее известным параметром, полезно знать, почему его не следует использовать в коде уровня доступа к данным.
По умолчанию это свойство отключено, и для его включения необходимо указать следующее свойство конфигурации:
Учитывая следующие сущности:
При наличии этого свойства конфигурации следующие фрагменты кода могут быть выполнены без исключения LazyInitializationException
:
Listcomments = 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
предотвращается гораздо более эффективным способом.