我在PostgreSQL 11中有一个SP,其结构如下所示。
因此,此SP的想法是,如果某些语句失败,我们不会丢失所有更新/插入(在SP中完成)。我们只会丢失最后一次提交后发生的更新/插入。
好,所以我从DBeaver调用此SP,并且得到了预期的行为,在前两次提交之前所做的更改仍保留在数据库中,即被持久化到数据库中。
现在,我正尝试使用 Spring 4.3.21 从Java代码调用相同的SP, JDBC驱动程序postgresql-42.2.5.jar 和休眠版本5 。
(1)调用此SP的Java方法像<prop key="process*">PROPAGATION_REQUIRED,-Exception</prop>
一样配置为Spring事务处理。
好的...但是随后从Java代码中我得到了不同的行为(不是来自DBeaver的行为)。从Java中,我现在得到以下错误:org.postgresql.util.PSQLException: ERROR: invalid transaction termination
,该错误来自第一次提交。
不管我做什么,我总是得到这个。
所以从SP代码看来,我无法提交Spring开始的事务?!为什么不允许我承诺?我究竟做错了什么?
以我想要的方式从Java / Spring调用SP的正确方法是什么?!
(2)另外...如果我尝试从非事务方法(在Spring的意义上为非事务方法)从Java / Spring调用SP,那么我会从Spring本身得到一个错误:需要事务。
所以...看来我没有办法从Java / Spring调用此SP并使前两次提交成功。
正确的方法是什么?
过去2-3天,我一直在为此苦苦挣扎。
-------------------------------------------------------------------------
DROP PROCEDURE IF EXISTS yb.test123;
CREATE OR REPLACE PROCEDURE yb.test123()
LANGUAGE plpgsql
AS $procedure$
DECLARE
cnt int;
c int;
BEGIN
--- do some inserts/updates - they all succeed
COMMIT; -- commit #1
--- do some inserts/updates - they all succeed
COMMIT; -- commit #2
--- do some inserts/updates - 1 of these fails
COMMIT; -- commit #3
END
$procedure$;