HIbernate commit() и flush()
Я много гуглил и читал о org.hibernate.Transaction.commit()
а также org.hibernate.Session.flush()
много, знаю назначение каждого метода, но все же есть вопрос.
Это хорошая практика, чтобы позвонить org.hibernate.Session.flush()
метод вручную? Как сказано в org.hibernate.Session
документы,
Должен вызываться в конце единицы работы, прежде чем совершать транзакцию и закрывать сеанс (в зависимости от режима сброса Transaction.commit() вызывает этот метод).
Не могли бы вы объяснить мне цель звонка org.hibernate.Session.flush()
вручную, если org.hibernate.Transaction.commit()
будет вызывать это автоматически?
Спасибо!
7 ответов
В 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
flush()
синхронизирует вашу базу данных с текущим состоянием объектов / объектов, хранящихся в памяти, но не фиксирует транзакцию. Итак, если вы получите какое-либо исключение после flush()
называется, то транзакция будет откатана. Вы можете синхронизировать базу данных с небольшими порциями данных, используя flush()
вместо фиксации больших данных сразу, используя commit()
и столкнуться с риском получения исключения из нехватки памяти.
commit()
сделает данные, хранящиеся в базе данных, постоянными. Вы не сможете откатить свою транзакцию, как только commit()
преуспевает.
Один из распространенных случаев явной очистки - это когда вы создаете новую постоянную сущность и хотите, чтобы ей был создан и назначен искусственный первичный ключ, чтобы вы могли использовать его позже в той же транзакции. В этом случае вызов flush приведет к тому, что вашей сущности будет присвоен идентификатор.
Другой случай, если в кеше 1-го уровня много вещей, и вы хотите периодически очищать его (чтобы уменьшить объем памяти, используемый кешем), но вы все равно хотите зафиксировать все вместе, Это тот случай, который охватывает ответ Алексея (+1 от меня).
промывать(); Сброс - это процесс синхронизации основного постоянного хранилища с постоянным состоянием, хранящимся в памяти. Он будет обновлять или вставлять в ваши таблицы в выполняющейся транзакции, но он может не зафиксировать эти изменения.
Вы должны очистить в пакетной обработке, иначе это может дать OutOfMemoryException.
Commit (); При коммите будет выполняться фиксация базы данных. Когда у вас есть постоянный объект и вы изменяете значение в нем, он становится грязным, и спящий режим должен сбрасывать эти изменения на ваш уровень персистентности. Так что вы должны фиксировать, но это также завершает единицу работы.transaction.commit ()
Обычно не рекомендуется вызывать flush явно, если в этом нет необходимости. Hibernate обычно автоматически вызывает Flush в конце транзакции, и мы должны позволить ей выполнить свою работу. Теперь, есть некоторые случаи, когда вам может понадобиться явно вызвать 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());
}
Также обратите внимание, что явная очистка не вызывает фиксацию базы данных, фиксация базы данных выполняется только в конце транзакции, поэтому, если возникает какая-либо ошибка времени выполнения после вызова сброса, изменения все равно будут выполнять откат.
По умолчанию режим сброса имеет значение AUTO, что означает, что: "Сеанс иногда сбрасывается перед выполнением запроса, чтобы гарантировать, что запросы никогда не возвращают устаревшее состояние", но большая часть времени сеанса сбрасывается, когда вы фиксируете свои изменения. Ручной вызов метода flush полезен, когда вы используете FlushMode=MANUAL или хотите выполнить некоторую оптимизацию. Но я никогда не делал этого, поэтому не могу дать вам практический совет.
session.flush() - это метод метода синхронизации, позволяющий последовательно вставлять данные в базу данных. Если мы используем этот метод, данные не будут храниться в базе данных, но будут храниться в кеше, если какое-либо исключение будет расти в середине, мы можем его обработать. Но commit() будет хранить данные в базе данных. Если мы храним больше данных, то может быть шанс выйти из исключения памяти, как, например, в программе JDBC в разделе "Сохранить точку".