Как заставить Hibernate читать внешние изменения базы данных - PullRequest
1 голос
/ 05 июля 2019

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

Давайте назовем их application #1 и application #2.

Предположим, у нас есть следующий сценарий:

  • база данных содержит таблицу с именем items (не имеет значения ее содержимое)
  • application #2 разработан в Spring Boot и в основном используется только для чтения данных из базы данных
  • application #2 извлекает элемент из базы данных
  • application #1 изменяет этот элемент
  • application #2 снова получает тот же элемент, но изменения не видны

Что я понял, прочитав много статей:

  • при получении application #2элемент, Hibernate сохраняет его в кэше первого уровня
  • изменения, которые вносятся в элемент с помощью application #1, являются внешними изменениями, и Hibernate не знает о них, и, следовательно, кэш не обновляется (происходит то же самое)когда вы делаете ручное изменение в базе данных)
  • вы не можете отключить кэш первого уровня Hibernate.

Итак, мой вопрос, можете ли вы заставить Hibernate обновлять сущности каждый раз, когда оничитать (или сделать явойти в базу данных) без явного вызова em.refresh(entity)?Проблема в том, что модуль бизнес-логики из application1 используется в качестве зависимости в application1, поэтому я могу вызывать только сервисные методы (т. Е. У меня нет доступа к entityManager или session ссылкам).

Ответы [ 4 ]

1 голос
/ 05 июля 2019

Кэш Hibernate L1 примерно эквивалентен транзакции БД, когда вы работаете в режиме изоляции с повторяющимся чтением. По сути, если вы читаете / записываете некоторые данные, при следующем запросе в контексте того же сеанса вы получите те же данные. Кроме того, в рамках одного и того же процесса сеансы работают независимо друг от друга, что означает, что 2 сеанса просматривают разные данные в кэше L1.

Если вы используете повторяемое чтение или меньше, то вам не стоит беспокоиться о кеше L1, так как вы можете столкнуться с этим сценарием независимо от ORM (или без ORM).

Я думаю, что вам нужно думать только о кеше L2 здесь. Кэш L2 - это то, что хранит данные и предполагает, что только hibernate осуществляет доступ к БД, что означает, что если в БД произойдут какие-то изменения, hibernate может не знать об этом. Если вы просто отключите кэш L2, вы будете отсортированы.

Дальнейшее чтение - Краткое описание уровней кэша гибернации

0 голосов
/ 06 июля 2019

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

Вы можете комментировать свою функцию таким образом

@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)

При запросе новой транзакции система генерирует новый сеанс гибернации, поэтому данные не будут в кеше.

0 голосов
/ 05 июля 2019

Вы можете попытаться использовать StatelessSession, но вы потеряете cascading и другие вещи.

https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#_statelesssession

https://stackoverflow.com/a/48978736/3405171

0 голосов
/ 05 июля 2019

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

session.evict(entity);

или

session.clear();

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...