2013-01-29 2 views
50

Я много гугл и много читал о и org.hibernate.Session.flush(), знаю цель каждого метода, но все еще есть вопрос.HIbernate commit() и flush()

Полезно ли позвонить по телефону org.hibernate.Session.flush()? Как сказано в org.hibernate.Session документы,

должен быть вызван в конце единицы работы, перед тем совершали сделки и закрытия сессии (в зависимости от флеш-режиме, Transaction.commit() вызывает этот метод).

Не могли бы вы объяснить мне цель вызова org.hibernate.Session.flush() вручную, если org.hibernate.Transaction.commit() будем называть его автоматически?

Спасибо!

+0

Вы можете ввести 'sessionFactory', используя аннотацию' @ Transactional', если вы заглянули в нее. Вам не понадобится, чтобы ваш код был транзакционным везде и далее (в некоторых случаях он требует). – Lion

+0

Я просто столкнулся с интересной ситуацией в своем коде, мне пришлось объединить сущность, у которой уже был идентификатор, созданный из клиентского приложения, а затем обновить один и тот же объект, чтобы получить поля сгенерированные с помощью базы данных, такие как дата и изменение даты. Без вызова session.flush() он выкидывал исключение, не найденное объектом, потому что вызов слияния иногда игнорируется до конца транзакции, когда я добавлял флеш сразу после вызова слияния, он заставляет hibernate выполнять фактический запрос, а затем позже обновлять объект работает, потому что теперь он существует в db! –

ответ

66

В руководстве Hibernate вы можете увидеть этот пример

Session session = sessionFactory.openSession(); 
Transaction tx = session.beginTransaction(); 


for (int i=0; i<100000; i++) { 
    Customer customer = new Customer(.....); 
    session.save(customer); 
    if (i % 20 == 0) { //20, same as the JDBC batch size 
     //flush a batch of inserts and release memory: 
     session.flush(); 
     session.clear(); 
    } 
} 

tx.commit(); 
session.close(); 

Без вызова смывного метода, кэш первого уровня будет сгенерировано OutOfMemoryException

Also you can look at this post about flushing

+0

Не могли бы вы дать ссылку на эту статью? – bsiamionau

+1

http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html/ch04.html#d5e976 –

+3

В этом ответе приведен конкретный случай, когда рекомендуется явно называть флеш, но я не думайте, что он обращается к общему вопросу о том, следует ли всегда это делать. –

2

По умолчанию режим смыва AUTO, что означает, что: «Сессия иногда очищается до выполнения запроса, чтобы гарантировать, что запросы никогда не возвращают состояние устаревания», но большая часть времени сеанса очищается, когда вы фиксируете свои изменения. Ручной вызов метода flush полезен, если вы используете FlushMode = MANUAL или хотите сделать какую-то оптимизацию. Но я никогда не делал этого, поэтому я не могу дать вам практические советы.

39

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

Другой случай - если в кеше 1-го уровня есть много вещей, и вы хотите периодически его очищать (чтобы уменьшить объем памяти, используемой кешем), но вы все еще хотите зафиксировать все вместе. Это тот случай, когда Aleksei's answer охватывает (+1 от меня).

+1

Благодарим за разъяснения! +1 – bsiamionau

+0

Если вы хотите получить доступ к сгенерированному ПК немедленно, я считаю, что вам также нужно вызвать '.refresh (...)' –

7

flush(); Промывка - это процесс синхронизации лежащего в основе постоянного хранилища с постоянным состоянием, хранящимся в памяти. Он будет обновляться или вставляться в ваши таблицы в текущей транзакции, но он не может выполнять эти изменения.

Вам необходимо промывать в пакетной обработке в противном случае он может дать OutOfMemoryException.

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

37

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

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

+0

@ Anand. хорошо сказано. – DEADEND

1

session.flush() метод synchronize означает вставлять данные в базу данных последовательно. Если мы используем этот метод, данные не будут храниться в базе данных, но будут храниться в кеше, если какое-либо исключение поднимется посередине, мы сможем справиться с этим , Но commit() будет хранить данные в базе данных, если мы будем хранить больше данных, тогда может возникнуть шанс выйти из исключения памяти. Как и в программе JDBC в точке сохранения.

0

Обычно это не рекомендуется явно называть флеш, если это не необходимо. Hibernate обычно автоматически вызывает Flush в конце транзакции, и мы должны позволить ему выполнять эту работу. Теперь есть некоторые случаи, когда вам может потребоваться явно вызвать flush, где вторая задача зависит от результата первой задачи Persistence, причем оба находятся внутри одной транзакции.

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

@Transactional 
void someServiceMethod(Entity entity){ 
    em.persist(entity); 
    em.flush() //need to explicitly flush in order to use id in next statement 
    doSomeThingElse(entity.getId());  
} 

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

Смежные вопросы