Entitymanager.flush() VS EntityManager.getTransaction(). Commit - что я должен предпочесть?
Что мне следует использовать при обновлении базы данных? Каковы плюсы и минусы с любым методом, и когда я должен использовать тот или иной?
public void disemployEmployee(Integer employeeId, Date endDate) {
Employee employee = (Employee)em.find("Employee", employeeId);
employee.getPeriod().setEndDate(endDate);
em.flush();
}
public void disemployEmployee(Integer employeeId, Date endDate) {
Employee employee = (Employee)em.find("Employee", employeeId);
em.getTransaction().begin();
employee.getPeriod().setEndDate(endDate);
em.getTransaction().commit();
}
Ответы
Ответ 1
В первом примере изменения данных отражаются в базе данных после обнаружения флеша, но они все еще находятся в транзакции.
Но во втором примере вы совершаете транзакцию немедленно. Поэтому изменения вносятся в базу данных, и транзакция также заканчивается там.
Иногда флеш может быть полезен для сохранения данных между текущей транзакцией и затем, наконец, фиксации изменений после этого. Таким образом, вы также можете отменить предыдущие изменения, если после этого возникнет некоторая проблема, например, для пакетной вставки/обновления.
Ответ 2
Вы прочитали javadoc для флеша и фиксации и знаете, что флеш предназначен только для транзакции внутри? Он сбрасывает (но не фиксирует), тогда как фиксация фиксирует данные (очевидно). Они различны; нет "предпочтения". Первый пример неверен и должен привести к исключению при вызове flush (TransactionRequiredException)
Ответ 3
Оба из ваших образцов кода не сохраняются или не объединяют состояние объекта, которое должно быть записано в DB.
Я не считаю целесообразным сравнивать EntityManager.flush()
и EnityManager.EntityTransaction.commit()
.
flush() ДОЛЖЕН быть заключен в контексте транзакции, и вам не нужно делать это явно, если это необходимо (в редких случаях), когда EntityTransaction.commit() делает это для вас.
Ссылка на эту ссылку Нужно ли в этой ситуации вызывать флеш() (интерфейс JPA)?
Обратитесь к этой ссылке Вопрос о том, как очистить JPA до того, как будет вызван запрос, для сценария использования flush()
Ответ 4
Я бы пошел по сделке, управляемой контейнером, когда это было возможно. Bean управляемые транзакции обычно требуют значительно большего количества кода из-за возможностей Exception. Кроме того, это больше подвержено ошибкам (откаты, управление ресурсами).
Тем не менее, я использовал бы флеш после фиксации в режиме управляемого контейнером. Таким образом, я могу уловить возможные PersistenceExceptions в моем модуле хранения и преобразовать его в более значимое исключение для моего модуля использования. Это потому, что я не хочу обрабатывать исключения для хранилища здесь, потому что я могу заменить модуль хранения на то, что не использует JPA..., который никогда не случался со мной:)
Ответ 5
Я думаю, что недостающая часть, flush() просто добавляет к источникам данных, чтобы быть готовыми к фиксации, дает фактические идентификаторы, но не сохраняется по умолчанию.
Итак, если вам нужно, чтобы flush() работал как commit(), вам нужно установить режим очистки для Commit в EntityManager с помощью:
void setFlushMode(FlushModeType flushMode)
Set the flush mode that applies to all objects contained in the persistence context.
Обратите внимание, что FlushModeType представляет собой перечисление с двумя этими значениями:
FlushModeType AUTO (по умолчанию) Поток выполняется при выполнении запроса. Поскольку: JPA 1.0 FlushModeType COMMIT Промывка происходит при транзакции совершить. Провайдер может выполнять сброс в другое время, но не требуется. Поскольку: JPA 1.0
Я надеюсь, что эта помощь