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

Спящий жизненный цикл сущности

Обзор и объяснение состояний, через которые проходят сущности Hibernate в жизненном цикле

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

1. Обзор

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

Понимание этих состояний как на концептуальном, так и на техническом уровне имеет важное значение для правильного использования Hibernate.

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

2. Методы помощников

На протяжении всего этого учебника мы будем последовательно использовать несколько методов помощников:

  • HibernateLifecycleUtil.getManagedEntities (сессия) – Мы будем использовать его, чтобы получить все управляемые сущности из Заседание внутренний магазин
  • DirtyDataInspector.getDirtyEntities () – мы собираемся использовать этот метод, чтобы получить список всех сущностей, которые были отмечены как “грязные”
  • HibernateLifecycleUtil.queryCount (запрос) – удобный способ сделать кол-во (к) запрос против встроенной базы данных

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

3. Это все о настойчивости Контекст

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

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

Теоретически говоря, настойчивость контексте является осуществлением Группа по работе рисунок. Он отслеживает все загруженные данные, отслеживает изменения этих данных и несет ответственность за то, чтобы в конечном итоге синхронизировать любые изменения обратно в базу данных в конце бизнес-транзакции.

JPA EntityManager и в спячке Сессионая являются реализацией настойчивость контексте понятие. На протяжении всей этой статьи мы будем использовать Hibernate Сессионая представлять настойчивость контексте.

Состояние жизненного цикла сущности hibernate объясняет, как сущность связана с настойчивость контексте , как мы увидим дальше.

4. Управляемая сущность

Управляемая сущность является представлением строки таблицы базы данных (хотя эта строка пока не обязательно будет существовать в базе данных).

Этим управляет запущенная в настоящее время Сессионая , и каждое изменение, сделанное на нем, будет отслеживаться и распространяться в базу данных .

Давайте понаблюдать за некоторым кодом, чтобы получить разъяснения.

Наше пример приложения определяет одну сущность, ФутболПлейер класс. При запуске мы будем инициализировать хранение данных с некоторыми выборочных данных:

+-------------------+-------+
| Name              |  ID   |
+-------------------+-------+
| Cristiano Ronaldo | 1     |
| Lionel Messi      | 2     |
| Gianluigi Buffon  | 3     |
+-------------------+-------+

Допустим, мы хотим изменить имя Буффона, чтобы начать с – мы хотим поставить в его полное имя Джанлуиджи Буффон вместо Джиджи Буффона.

Во-первых, мы должны начать нашу единицу работы, получив сеанс:

Session session = sessionFactory.openSession();

В серверной среде мы можем ввести Сессионая к нашему коду через прокси-сервер, осведомленный о контексте. Принцип остается прежним: нам нужна Сессионая инкапсулировать бизнес-транзакцию нашей единицы работы.

Далее, мы проинструктируем наших Сессионая для загрузки данных из постоянного магазина:

assertThat(getManagedEntities(session)).isEmpty();

List players = s.createQuery("from FootballPlayer").getResultList();

assertThat(getManagedEntities(session)).size().isEqualTo(3);

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

Далее мы выполняем запрос, который извлекает данные из базы данных, создает представление сущности данных и, наконец, возвращает объект для использования.

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

Теперь давайте изменим имя Джиджи:

Transaction transaction = session.getTransaction();
transaction.begin();

FootballPlayer gigiBuffon = players.stream()
  .filter(p -> p.getId() == 3)
  .findFirst()
  .get();

gigiBuffon.setName("Gianluigi Buffon");
transaction.commit();

assertThat(getDirtyEntities()).size().isEqualTo(1);
assertThat(getDirtyEntities().get(0).getName()).isEqualTo("Gianluigi Buffon");

4.1. Как это работает?

При вызове в транзакционные коммит () или флеш() , Сессионая найдете любую грязные сущностей из списка отслеживания и синхронизации состояния с базой данных.

Обратите внимание, что нам не нужно было звонить каким-либо способом уведомления сеанс что мы что-то изменили в нашей сущности – так как это управляемая сущность, все изменения распространяются в базу данных автоматически.

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

Смотрите главу о переходных сущностях ниже.

5. Отдельное образование

отдельные сущности это просто обычная сущность POJO значение удостоверения соответствует строке базы данных. Отличие от управляемой сущности в том, что она больше не отслеживается никакими настойчивость контексте .

Сущность может стать оторванной, когда Сессионая используется для загрузки он был закрыт, или когда мы называем Session.evict (сущность) или Session.clear () .

Давайте посмотрим на это в коде:

FootballPlayer cr7 = session.get(FootballPlayer.class, 1L);

assertThat(getManagedEntities(session)).size().isEqualTo(1);
assertThat(getManagedEntities(session).get(0).getId()).isEqualTo(cr7.getId());

session.evict(cr7);

assertThat(getManagedEntities(session)).size().isEqualTo(0);

Наш контекст настойчивости не будет отслеживать изменения в отдельных сущностях:

cr7.setName("CR7");
transaction.commit();

assertThat(getDirtyEntities()).isEmpty();

Session.merge (entity)/Session.update (entity) может (re) приложите сессионный :

FootballPlayer messi = session.get(FootballPlayer.class, 2L);

session.evict(messi);
messi.setName("Leo Messi");
transaction.commit();

assertThat(getDirtyEntities()).isEmpty();

transaction = startTransaction(session);
session.update(messi);
transaction.commit();

assertThat(getDirtyEntities()).size().isEqualTo(1);
assertThat(getDirtyEntities().get(0).getName()).isEqualTo("Leo Messi");

Для справки по обоим Session.merge () и Session.update () увидеть здесь .

5.1. Поле идентификации – это все, что имеет значение

Давайте посмотрим на следующую логику:

FootballPlayer gigi = new FootballPlayer();
gigi.setId(3);
gigi.setName("Gigi the Legend");
session.update(gigi);

В приведеном выше примере мы мгновенно обустроим сущность обычным способом через ее конструктора. Мы заселили поля значениями и установили идентификацию до 3, что соответствует идентификации постоянных данных, принадлежащих Джиджи Буффону. Вызов обновление () имеет точно такой же эффект, как если бы мы загрузили сущность из другого настойчивость контексте .

На самом деле, Сессионая не различает, откуда возникла повторно прикрепленная сущность.

Это довольно распространенный сценарий в веб-приложениях для построения отдельных сущностей от значений формы HTML.

Что касается Сессионая обеспокоена тем, что отдельная сущность является простой сущностью, значение личности которой соответствует постоянным данным.

Имейте в виду, что приведенный выше пример служит демо-цели. и мы должны точно знать, что мы делаем. В противном случае, мы могли бы в конечном итоге с нулевыми значениями по всей нашей сущности, если мы просто установить значение на поле мы хотим обновить, оставляя остальные нетронутыми (так, фактически нулевой).

6. Переходное образование

Переходное существо – это просто сущность объект, не имеет представления в стойких магазинах и не управляется никакими Сессионая .

Типичным примером переходной сущности было бы мгновенное воспроизведение новой сущности через ее конструктора.

Чтобы сделать переходную сущность стойкие , мы должны позвонить Session.save (entity) или Session.saveOrUpdate (сущность):

FootballPlayer neymar = new FootballPlayer();
neymar.setName("Neymar");
session.save(neymar);

assertThat(getManagedEntities(session)).size().isEqualTo(1);
assertThat(neymar.getId()).isNotNull();

int count = queryCount("select count(*) from Football_Player where name='Neymar'");

assertThat(count).isEqualTo(0);

transaction.commit();
count = queryCount("select count(*) from Football_Player where name='Neymar'");

assertThat(count).isEqualTo(1);

Как только мы выполним Session.save (entity) , сущности присваивается значение идентификации и управляется Сессионая . Однако он может быть недоступен в базе данных, поскольку операция INSERT может быть отложена до окончания единицы работы.

7. Удаленная сущность

Сущность находится в удаленном (удаленном) состоянии, если Session.delete (entity) был вызван, и Сессионая пометив сущность для удаления. Сама команда DELETE может быть выпущена в конце единицы работы.

Рассмотрим его в следующем коде:

session.delete(neymar);

assertThat(getManagedEntities(session).get(0).getStatus()).isEqualTo(Status.DELETED);

Однако обратите внимание, что сущность остается в постоянном контексте хранения до конца единицы работы.

8. Заключение

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

Как обычно, код, используемый в этой статье, можно найти более на GitHub .