2015-06-08 8 views
1

Для синхронизации и получения идентификаторов, созданных с помощью БД, я чувствую принуждение звонить по телефону EntityManager.flush() в нескольких местах.Когда НЕ использовать EntityManager.flush()?

Последствия, связанные с последствиями, есть причины не для звонка flush()?

Другими словами, существует ли какая-либо наблюдаемая разница для вызывающего метода моего (DAO, ...), если он делает/не flush()?

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

ответ

2

Вызов flush() Синхронизирует контекст персистентности с базой данных. Это в первую очередь требуется - если необходимо получить запрос (через JPQL и т. Д.).

Позже в стеке вызовов в базу данных, и если контекст persistence содержит грязное значение для любого из объектов, состояние которых может быть затронуто результатами запроса, тогда они должны быть синхронизированы. На самом деле по умолчанию FlushModeType для JPA запросов является AUTO

Когда запросы выполняются в рамках транзакции, если FlushModeType.AUTO устанавливается на запрос или TypedQuery объекта, или если вровень режим настройки для контекста Настойчивость Для объекта Query или TypedQuery не задан параметр AUTO (по умолчанию) и режим очистки , поставщик непрерывности несет ответственность за то, что все обновления до состояния всех объектов в контексте персистентности, которые могли бы потенциально повлиять на результат запроса видны для обработки запроса , Реализация поставщика сохранения может достичь этого путем промывки этих объектов в базу данных или некоторыми другими способами.

Так до тех пор, как вы запрашиваете объект через его состояние и не JPA запросы и результаты этих запросов не зависят от грязного состояния, то это плохо для выполнения вызова на одном уровне, как это предполагает повторено загрязнена проверка состояния а не просто в момент фиксации.

@Adams упомянул о своем опыте работы с OpenJPA, где флеш ломает несколько вещей, поэтому я предполагаю, что в разных реализациях есть проблемы.

+0

«Запрос объекта через его состояние, а не запросы JPA» - Что вы подразумеваете под «JPA-запросами»? 'em.find (...)', в отличие от 'em.createQuery (...)'? – JimmyB

+0

@ Ханно - Да точно.Запрос должен ударить по базе данных, и если есть ожидающее изменения в форме состояния грязного объекта, тогда возникнет несогласованность, если синхронизация будет выполнена с опозданием. – Shailendra

+1

Я думаю, что мы добираемся до важного момента здесь: даже если я никогда не буду скрывать явно, поставщик JPA может решить/должен сфотографироваться в некоторых точках, в зависимости от того, например. о том, какие запросы я выполняю и/или насколько провайдер может избежать попадания в БД с запросом на чтение. Таким образом, по сути, это в основном не предсказуемо, когда в последовательности операций чтения/записи произойдет неявный флеш. Из этого я заключаю, что я тоже могу создать флеш в любой момент, который я нахожу подходящим, не нарушая какого-либо контракта JPA. – JimmyB

1

Производительность в значительной степени суммирует большинство причин «не» для вызова флеша. Flush - это способ заставить все операторы изменений сразу же перемещаться в базу данных, а не накапливаться и отправляться как большая партия. Это может быть полезно, так как некоторые транзакции могут быть довольно большими и должны быть очищены, чтобы освободить память, а также заставить определенный порядок обновления ваших обновлений в базе данных.

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

+0

«когда некоторые изменения могут нарушить ограничение базы данных». Но даже если я никогда не буду краснеть, нет никакой гарантии, что данные будут * не * быть сброшены в любое время * до * совершить, правильно? – JimmyB

+0

Вы можете гарантировать, что данные не будут сброшены, если не будут выполняться определенные действия, которые заставили бы флеш. FlushModeType.COMMIT также не позволяет провайдеру решать запрос, требует флеша для работы, а EclipseLink разрешает варианты запросов в памяти, которые уменьшают потребность в запросах, чтобы очистить данные, чтобы увидеть изменения. – Chris

+0

Re: FlushModeType.COMMIT - Глядя на [docs] (http://docs.oracle.com/javaee/6/api/javax/persistence/FlushModeType.html#COMMIT), я обнаружил: «Поставщик * может скрываться в других случаях *, но не требуется. " Так что никаких гарантий с этой стороны. Я начинаю полагать, что явное промывание должно быть в порядке, в любом случае, поскольку сам поставщик может или не может быть явно скрыт в любое время. Спасибо за ваш вклад. – JimmyB