Вызывает ли JPA хранимую процедуру в той же транзакции?

У меня есть хранимая процедура, которая не обрабатывает транзакции (без фиксации и отката), и я вызываю ее из такого метода:

@Transactional
void work(Long id) {
   var entity = (id == null) ? create() || fetch(id);
   process(entity);
   repository.callProcedure(id);
} 

Этот код отлично работает для существующих объектов, но не работает для вновь созданных объектов. Кажется, что процедура Oracle не видит незафиксированные данные. Я считал, что процедура должна использовать одну и ту же транзакцию и поэтому действительно может видеть незафиксированные данные. Я бы предпочел иметь одну транзакцию, поэтому в случае сбоя процедуры Spring откатит изменения, внесенные как в Java, так и в процедуру.

Это должно быть возможно, но нам не хватает частей вашего кода. Аннотированы ли какие-либо компоненты или методы, которые вы вызываете? А как насчет процедуры Oracle, использует ли она автономную транзакцию? Но сначала: проверьте журнал SQL. Вы видите вставку? Возможно, вам придется выполнить очистку (baeldung.com/spring-jpa-flush), чтобы внести изменения в базу данных перед вызовом процедуры.

ewramner 01.07.2024 13:23

Существует множество методов, но все они частные и не имеют @transactional. entityManager.flush() — обходной путь. Хотя я был бы рад понять, зачем это нужно.

Leos Literak 01.07.2024 13:29
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
71
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Судя по вашему ответу на мой комментарий выше (flush - обходной путь, зачем он нужен) предполагаю, что это помогло. Вы не поделились своим кодом, но я предполагаю, что create делает что-то вроде:

entityManager.persist(myNewEntity);

Это создает объект в памяти и в конечном итоге создаст его в базе данных, но нет ничего, что заставило бы JPA немедленно выполнить вставку. Как правило, JPA будет ждать фиксации, ручной очистки или автоматической очистки перед запросом (когда JPA знает, что очистка необходима для получения правильных результатов).

Когда вы делаете собственные запросы/обновления базы данных за пределами JPA, вам сначала необходимо удалить все ожидающие изменения. Для этого и нужен флеш.

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

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

Leos Literak 02.07.2024 20:49

Другие вопросы по теме

Издевающийся объект, вызываемый в лямбда-выражении, вызванный из издевающегося объекта
SemanticException: элемент выбора в позиции 1 в списке выбора не имеет псевдонима при использовании подвыбора JPQL
Как сопоставить тип базы данных массива с Kotlin
Не удалось найти валидатор для ограничения «jakarta.validation.constraints.Pattern» — ошибка все еще появляется даже после удаления валидатора из класса
Как я могу разрешить JpaRepository <> в Spring MVC
Spring Data JPA/Hibernate: выражения конструктора JPQL - разница между использованием «нового (..)» и его неиспользованием
Ошибка создания bean-компонента с именем «entityManagerFactory» при обновлении приложения до Spring boot 3.3.0
Должен ли я применить @Transactional(readOnly = true) к простому методу запроса?
Обновление Spring Boot JPA с использованием составных первичных ключей
Не удалось безопасно определить назначение хранилища для интерфейса-кандидата репозитория, даже если объект помечен с помощью jakarta.persistence.Entity