Жизненный цикл EntityManager и постоянное взаимодействие клиент-сервер

#java #hibernate #jpa #entitymanager

#java #переход в спящий режим #jpa #entitymanager

Вопрос:

мы разрабатываем приложение (JavaSE-), которое взаимодействует со многими клиентами через постоянные tcp-соединения. Клиент подключается, выполняет некоторые / многие операции (которые обновляются в базе данных SQL) и закрывает приложение / отключается от сервера. Мы используем Hibernate-JPA и управляем жизненным циклом EntityManager самостоятельно, используя ThreadLocal-переменную. На самом деле мы создаем новый экземпляр EntityManager для каждого клиентского запроса, который пока работает нормально. Недавно мы немного профилировали и выяснили, что hibernate выполняет запрос ВЫБОРА к БД перед каждым оператором ОБНОВЛЕНИЯ. Это потому, что наши объекты находятся в отключенном состоянии, и каждый новый EntityManager сначала присоединяет объект к контексту сохранения. Это приводит к огромным затратам на SQL, когда сервер находится под нагрузкой (потому что у нас приложение с большим объемом записи), и мы пытаемся устранить эту утечку.

  • Сначала мы подумали о кэше 2-го уровня. Однако мы обнаружили, что hibernate аннулирует свои кэши запросов и коллекций всякий раз, когда добавляется или удаляется новый элемент.
  • С другой стороны, мы оцениваем, следует ли поддерживать EntityManager до тех пор, пока клиент входит в систему на сервере. Но мне интересно, является ли это «лучшей практикой», потому что есть некоторые недостатки: потокобезопасность, накладные расходы на управление экземплярами EntityManager и т.д.

Короче говоря: мы ищем способ избавиться от этих операторов ВЫБОРА перед каждым ОБНОВЛЕНИЕМ. Есть какие-нибудь идеи?

Ответ №1:

Один из возможных способов избавиться от select инструкций при повторном подключении отсоединенных объектов — использовать update() операцию, специфичную для гибернации, вместо merge() .

update() безоговорочно выполняет update инструкцию SQL и делает отдельный объект постоянным. Если постоянный объект с тем же идентификатором уже существует в сеансе, он выдает исключение. Таким образом, это хороший выбор, когда вы уверены, что:

  1. Отдельный объект содержит измененное состояние, которое должно быть сохранено в базе данных
  2. Сохранение этого состояния является основной целью открытия сеанса для этого запроса (т. Е. В этом сеансе не было других операций, которые загружали объект с тем же идентификатором)

В JPA 2.0 вы можете получить доступ к специфичным для гибернации операциям следующим образом:

 em.unwrap(Session.class).update(o);
  

Смотрите также:

Комментарии:

1. Звучит очень полезно для нас. Я попробую это.

Ответ №2:

Одним из возможных вариантов было бы использовать StatelessSession для инструкций обновления. Я успешно использовал его в своем приложении с большим объемом записи.