Spring JpaRepository: delete() с последующим сохранением() в той же транзакции

моя сущность имеет как автогенерированный первичный ключ (id), так и бизнес-ключ (пространство имен). Мне нужно обновить запись, заменив старый. Итак, я ищу его по бизнес-ключу, удаляю его и сохраняю новый объект. Это работает, если каждая операция в своей собственной транзакции. Но как только я помещаю их все в одну транзакцию, к моменту выполнения save() delete () еще не был выполнен, поэтому я получаю нарушение ограничения.

transactionTemplate.execute(status -> {
    MyEntity oldEntity = repository.findByNamespace(namespace);
    if (oldEntity != null) {
        repository.delete(oldEntity);
    }
    repository.save(newEntity);
    return null;
});

мне действительно удалось обойти его добавление

repository.flush();

но я действительно не понимаю, зачем мне нужен этот флеш ().

1 ответов


потому что репозитории.flush () сбрасывает изменения в базу данных, вызывая EntityManager.вспыхнуть.)( Поэтому, когда вы очищаете изменения после delete (), sql выполняется, и следующее сохранение не будет иметь проблем.

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

for entitymanager
EntityManager.setFlushMode(FlushModeType type);

or for query
Query.setFlushMode(FlushModeType type);

в Spring data JPA также есть эквивалентная настройка, я уверен, но я точно не знаю, какая из них.

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