Skip to main content

Hibernate

1. Hibernate Session. Javadoc называет её главным интерфейсом между java-приложением и Hibernate. Иногда её называют единицей работы или логической транзакцией. Основная функция сессии - обеспечить операции создания, чтения, удаления объектов. Объекты могут находиться в одном из 3 состояний (см. 2)
Сессия создается с помощью SessionFactory. SessionFactory знает конфигурацию ORM, её внутреннее состояния immutable. При вызове Configuration().configure() загружается файл hibernate.cfg.xml. После того, как конфигурация загружена, можно изменить настройки программно. Данные корректировки возможны только до создания экземпляра фабрики сессий.
// Initialize the Hibernate environment
Configuration cfg = new Configuration().configure();
// Create the session factory
ServiceRegistryBuilder srb = new ServiceRegistryBuilder();
ServiceRegistry sr = srb.applySettings(cfg.getProperties()).buildServiceRegistry();
SessionFactory factory = cfg.buildSessionFactory(sr);
// Obtain the new session object
Session session = factory.openSession();

https://developer.jboss.org/wiki/Sessionsandtransactions

2. Контекстные сессии и паттерны
Вместо openSession() можно использовать SessionFactory.getCurrentSession(). Вернет сессию, связанную с контекстом (с каким именно зависит от конфигурации). Её не надо открывать - она будет открыта при первом вызове, её не надо закрывать - при transaction.commit() с сессией случится flush. При работе с базой данных создается объект, который реализует интерфейс CurrentSessionContext. Hibernate включает три реализации этого интерфейса - JTASessionContext, ManagedSessionContext, ThreadLocalSessionContext.
В разных констекстах поведение сессии отличается: отличаются границы сессии, границы транзакции и работа по очистке.
JTASessionContext: контекст сессии определяется управляемой JTA транзакцией. При commit транзакции сессия флашится, очищается и закрывается. getCurrentSession() получит сессию, связанную с глобальной транзакциуй (?) (создаст, если не существует).
ThreadLocalSessionContext для юнит тестов и standalone приложений. жизненный цикл определяется потоком. Работу по очистке выполняет jdbc транзакция (?). getCurrentSession() получит сессию, связанную с потоком (создаст, если не существует).
ManagedSessionContext тоже связана с потоком, но может быть расширена на несколько. Мы управляем такой сессией, ее надо будет очистить и закрыть вручную. Подходит для продолжительных бесед (conversation) для логических единиц работы.

Если думать о транзакции как о неделимой единице работы с базой, то на протяжении всего @Transactional метода в java коде объекты должны быть в контексте, то есть сессия должна длиться то же время, что и транзакция.

Паттерны работы с сессиями:
Session per request - одна сессия на один запрос пользователя. Удобно, если используется один DAO: начали транзакцию (сессия с JTA контекстом) в начале метода, в конце метода закончили.
Session per conversation - здесь подходит ManagedSessionContext, так как между созданием и завершением сессии могут быть выполнены несколько действий в разных местах кода.
Session per operation - антипаттерн, когда отдельная сессия для всего: при работе с несколькими DAO, в каждом из них своя сессия и свои транзакции.

3. Что такое flush?
При изменении PersistentContext (например, добавили или изменили объекты) его состояние перестает соответствовать состоянию базы данных. Только после flush() изменения в Hibernate объектах вносятся в таблицы в базе данных.

4. С точки зрения Hibernate объект может находиться в одном из следующих состояний:
Transient - только создан с помощью new. Еще не связан с hibernate session.
Persistent - объект имеет представление в базе данных, у объекта есть id. Объект есть в scope сессии.
Detached - это объект, который был persistent, но сессия, с которой он был связан, завершена.



5. Что есть dirty checking?
Начнем издалека. Hibernate Session cодержит объект PersistentContext, который поддерживает кэш прочитанных из базы объектов в памяти (как map). При чтении из базы в памяти создается snapshot объекта. При завершении сессии Hibernate сравнивает текущее состояние объекта со snapshot'ом в памяти. Если объект изменился, соответствующая SQL команда ставится в очередь на выполнение. Dirty checking - это проверка изменения данных: изменился ли объект и надо ли его будет обновить в базе.

6. Отличие load() и get().
- Если объекта с данным id нет в БД, то get() вернет null, а load() выбросит исключение. Использовать load() только в том случае, если объект должен быть в базе, а его отсутствие - исключительная ситуация.
- get() возвращает реальный объект - идет select в БД, а load() возвращает proxy объект без обращения к БД. Select будет выполнен только после обращения к свойствам proxy или не будет выполнен вообще, если нам надо связать два объекта.

7. Lazy load
Определяет, будет ли дочерний объект загружен при загрузке родителя. По умолчанию true.
TODO: Proxy?

8. Кэширование в Hibernate
Есть first-level cache и second-level cache.

  • Кэш первого уровня связан с сессией. Его нельзя отключить. Хранит хоть раз загруженные объекты. Если был выполнен get(), а через некоторое время еще раз get() с тем же id, то будет только один запрос к базе. В первую очередь кэш используется чтобы уменьшить количество SQL-запросов. Например если объект модифицировался несколько раз в одной и той же транзакции, то Hibernate сгенерирует только один UPDATE.
  • Кеш второго уровня привязан к фабрике сессий, то есть действует для всего приложения. Конкретную реализацию предоставляет провайдер (EHCache, OSCache, ...). Хранит не объекты, а массив строк / чисел (занимает меньше памяти) как map (id - ключ, массив - значение). Чтение из кеша второго уровня происходит только в том случае, если нужный объект не был найден в кеше первого уровня.
  • Кэш запросов хранит результаты запросов. Кэш запросов не хранит сами объекты, хранит идентификаторы. Поэтому его бесполезно использовать без кэша второго уровня. Hibernate приводит конфигурацию кэша запросов в разделе о кэше второго уровня.
Стратегии кеширования задаются для объектов или в xml или в аннотации:

  • Read-only: эта стратегия используется когда данные вычитываются, но никогда не обновляется. Самая простая и производительная стратегия
  • Read/write: может быть использована, когда данные должны обновляться.
  • Nonstrict read/write: эта стратегия не гарантирует, что две транзакции не модифицируют одни и те же данные синхронно.
  • Transactional: полноценное кэширование транзакций. Доступно только в JTA окружении.

9. Fetching Strategies

10. Connection Pool
Hibernate может соединяться с БД через несколько механизмов:
- встроенный пул соединений - не для продакшена;
- c3p0 или proxool - сторонние пулы соединений;
- javax.sql.DataSource - если пул соединений предоставляет сервер как DataSource, а мы через JNDI ищем его.

11. Mapping
- с использованием аннотаций (JPA 2 аннотации);
- с использованием JPA 2 XML deployment descriptor;
- с использованием Hibernate legacy XML (hbm.xml)


К собеседованиям: что такое ORM, Lazy Loading, Unit of Work, проблема N+1...

Comments

Popular posts from this blog

Блочный, строчный, ...

Сборник советов: 1. Прижать элемент к нижнему краю контейнера: 2 . Две колонки: 3 . Что означает символ ">" в селекторе? Означает, что будут выбраны только прямые потомки. По-умному, direct descendant combinator. Иными словами, если есть: То "div a {color: blue;}" изменит цвет всех ссылок, а "div > a {color: blue;}" - только первой и третьей. 4 . TODO

Первые шаги в Selenium

Цель расплывчата: понять и сделать хоть что-нибудь =) Selenium Selenium - группа продуктов. Отличное описание в статье Что такое Selenium? Selenium IDE - плагин для Firefox, позволяет записать тест, выполняя действия в браузере. Казалось бы, Selenium WebDriver должен дать больше возможностей: всё таки не из графического интерфейса тесты пишем, а с помощью языка программирования, но интересная мысль в другой статье того же автора  Что такое Selenium WebDriver? : "... WebDriver не имеет прямого отношения к тестированию. Он всего лишь предоставляет автотестам доступ к браузеру. На этом его функции заканчиваются.Структурирование, группировку и запуск тестов, а также генерацию отчётов о тестировании, обеспечивает фреймворк тестирования, такой как JUnit или TestNG для Java, .."  Локаторы Выбрать элемент на странице можно используя локаторы. Локаторы (в Selenium IDE в поле target) используют DOM, XPath или CSS (или просто ищут по id/name). Полезное: XPath: XML Path La...