Как использовать EntityManager, чтобы найти сущность по идентификатору, не затрагивая кеш в одном запросе? - PullRequest
0 голосов
/ 18 января 2019

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

Этот раздел кода выглядит следующим образом:

MyEntity entity = entityManager.find(MyEntity.class, key);
entityManager.refresh(entity, LockModeType.PESSIMISTIC_WRITE);

Работает нормально, но, как я понимаю, в случае, когда в кэше hibernate нет сущности, мы будем использовать 2 транзакции чтения в базу данных. 1-я транзакция для поиска объекта по идентификатору и другая транзакция для обновления и блокировки объекта. Можно ли в таком сценарии использовать только одну транзакцию?

Я хотел бы представить что-то вроде:

boolean skipCache = true;
MyEntity entity = entityManager.find(MyEntity.class, key, 
    LockModeType.PESSIMISTIC_WRITE, skipCache);

Но нет такого параметра, как skipCache. Есть ли другой подход для чтения сущности по идентификатору непосредственно из базы данных, используя EntityManager?

UPDATE:

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

MyEntity entity = entityManager.find(MyEntity.class, key, LockModeType.PESSIMISTIC_WRITE);

Вопрос в том, чтобы пропустить кеш, а не в блокировке.

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Я только что нашел метод getReference в EntityManager, который получает экземпляр, состояние которого можно лениво извлекать. Как сказано в документации:

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

В качестве возможного решения для поиска и блокировки актуальной сущности по id в одном запросе мы можем использовать следующий код:

MyEntity entity = entityManager.getReference(MyEntity.class, key);
entityManager.refresh(entity, LockModeType.PESSIMISTIC_WRITE);

Этот запрос создаст объект (без запроса к базе данных), а затем обновит и заблокирует объект.

0 голосов
/ 18 января 2019

Почему бы напрямую не передать запрошенную блокировку вместе с самим запросом?

MyEntity entity = entityManager.find(MyEntity.class, key, LockModeType.PESSIMISTIC_WRITE);

Насколько я понимаю, это делает именно то, что вы хотели. ( Документация )

...