概述:
我有一个存储的plpgsql
函数,该函数在其中一个表中进行更新。在更新之前,它会评估条件,如果条件评估为true
,则会引发异常。
在Java代码中,有一个服务层方法,可以在循环中使用不同的参数多次调用此存储过程。使用spring注释标记为事务性的方法。
问题:
假设基于传入的参数,存储过程应该两次调用两次。在第一次调用期间,不会在SP内部引发异常,因此更新成功进行。在第二次调用时,引发异常,然后由配置的@ExceptionHandler
处理异常。问题是,Spring不会回滚由第一次调用存储过程所做的更新。
spring是否有可能回滚第一个过程调用所做的更改,如果是,那么当前设置会出现什么问题?
示例代码:
存储过程:
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();
}
}
}