Вызов entityManager.flush - эффект от его вызова дважды, один раз или вообще не - PullRequest
0 голосов
/ 17 июня 2019

Нужно ли вызывать entityManager.flush() или данные записываются автоматически при выходе, когда метод имеет аннотацию @Transactional?

Кроме того, если я вызываю его дважды, всегда ли я получаю исключение без транзакции?

    @PersistenceContext(unitName = "CONFIGURATION", type = PersistenceContextType.TRANSACTION)
    private EntityManager entityManager;

@Transactional
    public boolean generate() {
        doStuffToDatabase();
        //entitymanager.flush();
        //entitymanager.flush(); //If I call it twice do I always get a no transaction exception?
    }

Ответы [ 2 ]

1 голос
/ 17 июня 2019

Когда метод @Transactional завершится успешно, транзакция будет зафиксирована. Перед совершением транзакции она автоматически вызовет flush() за сценой, если вы не вызовете ее явно.

flush() немедленно приведет к тому, что JPA выдаст SQL для вставки или обновления связанных записей базы данных, если есть какие-либо ожидающие изменения в контексте постоянства. Повторный вызов сброса сразу после первого сброса не имеет смысла, так как все ожидающие изменения в контексте постоянства уже обновляются до базы данных при первом сбрасывании.

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

1 голос
/ 17 июня 2019

Когда вы изменяете сущности внутри транзакции, вы на самом деле изменяете не базу данных, а модель строк в памяти.Когда ваша транзакция будет принята, изменения в модели в памяти будут сброшены в базу данных, что означает, что будут выполнены необходимые SQL-запросы для приведения состояния базы данных в состояние модели.

При вызове entityManager.flush вручную все, что вы делаете - синхронизируете эти изменения до завершения транзакции.Это имеет несколько последствий:

  • Если ваша транзакция заканчивается отменой (исключение возникает после вызова сброса), Hibernate / JPA должен будет выполнить откат базы данных, что приведет к снижению производительности.
  • Если состояние вашей модели заканчивается нарушением ограничения в базе данных, ручная очистка вызовет эту ошибку на более ранней стадии.Это обычно прерывает выполнение вашей Java при вызове сброса, а не во время фиксации транзакции.

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

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

...