HIbernate commit () и flush()


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

это хорошая практика, чтобы позвонить org.hibernate.Session.flush() способ вручную? Как сказано в org.hibernate.Session docs,

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

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

спасибо!

7 54

7 ответов:

в руководстве 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();

без вызова метода flush ваш кэш первого уровня выбросит исключение OutOfMemoryException

также вы можете посмотреть на этот пост про смывание

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

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

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

другой случай, если есть много вещей в кэше 1-го уровня, и вы хотели бы периодически очищать его (чтобы уменьшить объем памяти, используемой кэшем), но вы все еще хотите совершить все это вместе. Это тот случай, что Алексея обложки (+1 от меня).

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

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

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

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

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

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

@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());    
}

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

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