Откат изменений, внесенных хранимыми процедурами (PostgreSQL) с помощью Spring + Hibernate - PullRequest
0 голосов
/ 29 августа 2018

Обзор:

У меня есть сохраненная функция plpgsql, которая выполняет обновление в одной из таблиц. Перед обновлением он оценивает условие и выдает исключение, если условие оценивается как true. В Java-коде есть метод уровня сервиса, который несколько раз вызывает эту хранимую процедуру с разными параметрами в цикле. Метод помечен как транзакционный с весенней аннотацией.

Проблема:

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

Может ли пружина откатить изменения, сделанные при первом вызове процедуры, и если да, то в чем может быть проблема с текущей настройкой?

Пример кода:

Хранимая процедура:

create or replace function my_function(entity_id uuid)
  returns integer
language plpgsql
as $$
declare
  r record;
begin

  select * into r from my_table where id = entity_id;

  if (r.my_value > 10) 
  then
    raise exception 'Exception message'
    using errcode ='12345', hint = 'Exception hint';
  end if;

  update my_table
  set my_date = now()
  where id = entity_id;

  return 0;
end;
$$;

Способ обслуживания:

@Transactional
public void update(final List<UUID> ids) {
    for (final UUID id : ids) {
      storedProcedureRepository.myFunction(id);
    }
}

Метод репозитория:

@Transactional
@Override
public Optional<Integer> myFunction(final UUID entityId) {
    return getResultSingle("myFunction", query -> {
        query.setParameter("entity_id", entityId);
    });
}

private <T> Optional<T> getResultSingle(String procedureName, Consumer<StoredProcedureQuery> params) {
    EntityManager em = null;
    try {
        em = emf.createEntityManager();
        StoredProcedureQuery query = em.createNamedStoredProcedureQuery(procedureName);
        params.accept(query);
        query.execute();
        T result = (T) query.getSingleResult();
        return (result == null) ? Optional.empty() : Optional.of(result);

    } finally {
        if (em != null && em.isOpen()) {
            em.close();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...