Какая польза от session.flush () в Hibernate

110

Когда мы обновляем запись, мы можем использовать session.flush()Hibernate. Что нужно flush()?

ЧАНТИ
источник

Ответы:

138

Сброс сеанса заставляет Hibernate синхронизировать состояние в памяти Sessionс базой данных (т.е. записывать изменения в базу данных). По умолчанию Hibernate автоматически сбрасывает изменения за вас:

  • перед выполнением некоторых запросов
  • когда транзакция совершается

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

Паскаль Тивент
источник
8
Обратите внимание, что этот ответ описывает поведение гибернации ПО УМОЛЧАНИЮ: поведение сброса можно изменить с помощью параметра режима очистки. Подробности находятся в docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/… (версия 3.5).
SteveT
1
Я нашел документ, в котором сказано именно то, что вы говорите, но у меня есть вопрос, что будет приоритетом: предположим: 1) У меня есть класс, в котором я сохраняю объект с помощью кода, id = session.save(obj);и транзакция фиксируется на следующей строке, но obj не сохраняется в БД, почему? 2) Я сохранил obj, используя session.save(obj);с фиксацией, а при возврате я использовал return obj.getprimaryID();В этом случае obj сохраняется в БД. Так почему происходит такое поведение?
Amogh
74

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

Это то же самое, что открыть 2 сеанса команд SQL. И изменения, сделанные за 1 сеанс, не видны другим, пока не будут зафиксированы.

Кошик Леле
источник
12
Что ж - изменения могут быть слегка заметны. Например, незафиксированная строка может создать блокировку для вставленной, но незафиксированной строки и отложить вставку той же строки другим сеансом до тех пор, пока транзакция не будет зафиксирована или откат. Так что это не совсем незаметно.
rghome
2
Я искал информацию по всей сети, и это ответ, который наконец заставил меня понять. Спасибо.
Сиддхартха
какой смысл помещать .flush () в цикл for, тогда, если commit () выполняет сброс в конце?
Eildosa
@Kaushik Lele В чем смысл flush (), если данные не видны после сброса? Не могли бы вы подробнее рассказать о некоторых более тонких случаях использования, когда это пригодится?
java_geek
28

Я знаю только то, что когда мы вызываем, session.flush()наши операторы выполняются в базе данных, но не фиксируются.

Предположим, мы не вызываем flush()метод для объекта сеанса, и если мы вызываем метод фиксации, он будет выполнять внутреннюю работу по выполнению операторов в базе данных, а затем фиксации.

commit=flush+commit (в случае функциональности)

Таким образом, я прихожу к выводу, что когда мы вызываем метод flush () для объекта Session, он не получает фиксацию, а попадает в базу данных и выполняет запрос, а также получает откат.

Для фиксации мы используем commit () для объекта транзакции.

Шоаиб Чикате
источник
Не могли бы вы подробнее рассказать, зачем нужен смыв?
java_geek
14

При очистке сеанса данные, которые в данный момент находятся в сеансе, синхронизируются с данными в базе данных.

Подробнее на сайте Hibernate:

flush()полезно, потому что нет абсолютно никаких гарантий относительно того, когда сеанс выполняет вызовы JDBC, только порядок, в котором они выполняются, за исключением того, что вы используете flush().

мику
источник
Можете ли вы представить сценарий, когда пользователю следует беспокоиться о последовательности? Использование гибернации должно сделать вещи, связанные с БД, прозрачными для пользователя. Когда мы выполняем «коммит», сброс происходит автоматически. Каков сценарий, при котором вы выполняете сброс, но не фиксируете?
Кошик Леле
1
@KaushikLele, вы можете обратиться к этому вопросу stackoverflow.com/questions/37382872/…
GMsoF
10

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

Например, если вы создаете save()новый объект EmailAddress, который имеет уникальное ограничение на адрес, вы не получите сообщение об ошибке, пока не зафиксируете.

Вызов flush()заставляет строку быть вставленной, вызывая исключение, если есть дубликат.

Однако после исключения вам придется откатить сеанс.

rghome
источник
4

Я просто хотел бы объединить все ответы, данные выше, а также связать метод Flush () с Session.save (), чтобы придать большее значение

Hibernate save () можно использовать для сохранения объекта в базе данных. Мы можем вызывать этот метод вне транзакции, поэтому мне не нравится этот метод для сохранения данных. Если мы используем это без транзакции и у нас есть каскадирование между сущностями, то будет сохранена только основная сущность, если мы не очистим сеанс.

flush (): принудительно очищает сеанс. Он используется для синхронизации данных сеанса с базой данных.

Когда вы вызываете session.flush (), операторы выполняются в базе данных, но не фиксируются. Если вы не вызываете session.flush () и если вы вызываете session.commit (), внутренний метод commit () выполняет оператор и фиксируется.

Итак, commit () = flush + commit. Таким образом, session.flush () просто выполняет операторы в базе данных (но не фиксирует), а операторы больше НЕ В ПАМЯТИ. Это просто заставляет сеанс промывать.

Несколько важных моментов:

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

Сундар Гсв
источник
3

flush() Метод вызывает Hibernate промывать сессию. Вы можете настроить Hibernate для использования режима очистки для сеанса с помощью setFlushMode()метода. Чтобы получить режим очистки для текущего сеанса, вы можете использовать getFlushMode()метод. Чтобы проверить, грязная ли сессия, вы можете использовать isDirty()метод. По умолчанию Hibernate управляет сбросом сеансов.

Как указано в документации:

https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/chapters/flushing/Flushing.html

Промывка

Сброс - это процесс синхронизации состояния контекста постоянства с базовой базой данных. EntityManagerИ гибернации Sessionвыставить набор методов, с помощью которых разработчик может изменять постоянное состояние субъекта.

Контекст персистентности действует как транзакционный кэш с отложенной записью, помещая в очередь любое изменение состояния объекта. Как и любой кэш с отложенной записью, изменения сначала применяются в памяти и синхронизируются с базой данных во время очистки. Вровень операция принимает каждое изменение состояния лица и переводит его в INSERT, UPDATEили DELETEзаявление.

Стратегия очистки задается flushMode текущего запущенного сеанса Hibernate. Хотя JPA определяет только две стратегии очистки ( AUTOи COMMIT), Hibernate имеет гораздо более широкий спектр типов очистки:

  • ALWAYS: Очищает сеанс перед каждым запросом;
  • AUTO: Это режим по умолчанию, и он очищает сеанс только при необходимости;
  • COMMIT: Сессия пытается отложить очистку до тех пор, пока текущая транзакция не будет зафиксирована, хотя она также может быть сброшена преждевременно;
  • MANUAL: Сброс сеанса делегируется приложению, которое должно вызывать Session.flush()явно, чтобы применить изменения контекста постоянства.

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

  • до совершения Транзакции;
  • перед выполнением запроса JPQL / HQL, который перекрывается с действиями объекта в очереди;
  • перед выполнением любого собственного SQL-запроса, не имеющего зарегистрированной синхронизации.

источник
1

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

Johanwannheden
источник
0

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

lennoxGER
источник