通过存储过程(PostgreSQL)使用Spring + Hibernate

时间:2018-08-29 11:02:12

标签: java hibernate plpgsql spring-transactions

概述:

我有一个存储的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();
        }
    }
}

0 个答案:

没有答案