Hibernate: flush() и commit()

Это хорошая практика, чтобы звонить org.hibernate.Session.flush() отдельно?

Как сказано в org.hibernate.Session документах,

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

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

Ответ 1

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

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

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

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

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

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

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

Ответ 5

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

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

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

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

Ответ 6

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

Ответ 7

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