У меня есть хранимая процедура, которая не обрабатывает транзакции (без фиксации и отката), и я вызываю ее из такого метода:
@Transactional
void work(Long id) {
var entity = (id == null) ? create() || fetch(id);
process(entity);
repository.callProcedure(id);
}
Этот код отлично работает для существующих объектов, но не работает для вновь созданных объектов. Кажется, что процедура Oracle не видит незафиксированные данные. Я считал, что процедура должна использовать одну и ту же транзакцию и поэтому действительно может видеть незафиксированные данные. Я бы предпочел иметь одну транзакцию, поэтому в случае сбоя процедуры Spring откатит изменения, внесенные как в Java, так и в процедуру.
Существует множество методов, но все они частные и не имеют @transactional. entityManager.flush() — обходной путь. Хотя я был бы рад понять, зачем это нужно.
Судя по вашему ответу на мой комментарий выше (flush - обходной путь, зачем он нужен) предполагаю, что это помогло. Вы не поделились своим кодом, но я предполагаю, что create
делает что-то вроде:
entityManager.persist(myNewEntity);
Это создает объект в памяти и в конечном итоге создаст его в базе данных, но нет ничего, что заставило бы JPA немедленно выполнить вставку. Как правило, JPA будет ждать фиксации, ручной очистки или автоматической очистки перед запросом (когда JPA знает, что очистка необходима для получения правильных результатов).
Когда вы делаете собственные запросы/обновления базы данных за пределами JPA, вам сначала необходимо удалить все ожидающие изменения. Для этого и нужен флеш.
Не очищайте данные «на всякий случай», так как это снижает производительность, но в этом случае вы знаете, что у вас есть ожидающие изменения (вы только что создали объект), которые процедура должна видеть. В такой ситуации лучше всего использовать флеш.
Да, я тоже это понял. Объекты, сохраненные jparepository, ожидают в кеше L2, поэтому очистка действительно необходима. Если бы я включил ведение журнала в спящем режиме, я бы заметил это раньше.
Это должно быть возможно, но нам не хватает частей вашего кода. Аннотированы ли какие-либо компоненты или методы, которые вы вызываете? А как насчет процедуры Oracle, использует ли она автономную транзакцию? Но сначала: проверьте журнал SQL. Вы видите вставку? Возможно, вам придется выполнить очистку (baeldung.com/spring-jpa-flush), чтобы внести изменения в базу данных перед вызовом процедуры.