存储过程 Postgres 和 Java

Posted

技术标签:

【中文标题】存储过程 Postgres 和 Java【英文标题】:Stored Procedure Postgres and Java 【发布时间】:2015-01-26 15:33:40 【问题描述】:

我正在尝试从我的 java 应用程序中运行 Postgres 中的存储过程,这是该过程:

CREATE OR REPLACE FUNCTION geraCodigo() RETURNS integer AS $a$
DECLARE
codigo varchar;
codigoNovo varchar;
maximoRegistros integer;
contador integer := 1;
quantidadeCaracteres integer;
BEGIN
maximoRegistros := (SELECT count(id) FROM gisTemp);
RAISE NOTICE 'Contador %  ',contador;
RAISE NOTICE 'maximoRegistros %  ',maximoRegistros;
LOOP
RAISE NOTICE 'Contador %  ',contador;
IF (SELECT tipoTensao FROM gisTemp WHERE id = contador) = 'MT' THEN

    /*CHECA DIGITO 5 DO codConsumidor E PROCESSA DE ACORDO COM RESULTADO */
    IF (SELECT substring(codConsumidor from 4 for 1) FROM gisTemp WHERE id = contador) = '1' THEN

        quantidadeCaracteres = (SELECT char_length((SELECT substring(codConsumidor from 4 for 10) FROM gisTemp WHERE id = contador)));
        IF (quantidadeCaracteres) < 10 THEN
            LOOP
            BEGIN
            UPDATE gisTemp SET idsap = concat('0',(SELECT substring(codConsumidor from 4 for 10) FROM gisTemp WHERE id = contador)) WHERE id = contador;
            quantidadeCaracteres := quantidadeCaracteres + 1;
            EXCEPTION WHEN invalid_text_representation THEN
            ------ NÃO FAZ NADA
            END;
            EXIT WHEN quantidadeCaracteres >= 10;
            END LOOP;
        ELSE
        UPDATE gisTemp SET idsap = (SELECT substring(codConsumidor from 4 for 10) FROM gisTemp WHERE id = contador) WHERE id = contador;
        END IF;

    ELSIF (SELECT substring(codConsumidor from 4 for 1) FROM gisTemp WHERE id = contador) = '2' THEN

        quantidadeCaracteres = (SELECT char_length((SELECT substring(codConsumidor from 4 for 10) FROM gisTemp WHERE id = contador)));
        IF (quantidadeCaracteres) < 10 THEN
            LOOP
            BEGIN
            UPDATE gisTemp SET idsap = concat('0',(SELECT substring(codConsumidor from 4 for 10) FROM gisTemp WHERE id = contador)) WHERE id = contador;
            quantidadeCaracteres := quantidadeCaracteres + 1;
            EXCEPTION WHEN invalid_text_representation THEN
            ------ NÃO FAZ NADA
            END;
            EXIT WHEN quantidadeCaracteres >= 10;
            END LOOP;
        ELSE
        UPDATE gisTemp SET idsap = (SELECT substring(codConsumidor from 4 for 10) FROM gisTemp WHERE id = contador) WHERE id = contador;
        END IF;

    ELSIF (SELECT substring(codConsumidor from 4 for 1) FROM gisTemp WHERE id = contador) = '0' THEN
        UPDATE gisTemp 
        SET idsap = concat((SELECT substring(codConsumidor from 0 for 4) FROM gisTemp WHERE id = contador),(SELECT substring(codConsumidor from 6 for 10) FROM gisTemp WHERE id = contador))
        WHERE id = contador;
    END IF;

ELSIF (SELECT tipoTensao FROM gisTemp WHERE id = contador) = 'BT' THEN
    /*CHECA codConsumidor, SE > 18900 PEGA SÓ NÚMEROS*/
    BEGIN
    IF (SELECT CAST((SELECT substring(codConsumidor from 4 for 10) FROM gisTemp WHERE id = contador) AS integer)) > 18900 THEN
        /*CHECA O TAMANHO DO IDSAP*/
        quantidadeCaracteres = (SELECT char_length((SELECT substring(codConsumidor from 4 for 10) FROM gisTemp WHERE id = contador)));
        IF (quantidadeCaracteres) < 10 THEN
            /*LOOP PARA ADICIONAR ZEROS A ESQUERDA*/
            LOOP
            BEGIN
            UPDATE gisTemp SET idsap = concat('0',(SELECT substring(codConsumidor from 4 for 10) FROM gisTemp WHERE id = contador)) WHERE id = contador;
            quantidadeCaracteres := quantidadeCaracteres + 1;
            EXCEPTION WHEN invalid_text_representation THEN
            ------ NÃO FAZ NADA
            END;
            EXIT WHEN quantidadeCaracteres >= 10;
            END LOOP;
        ELSE
            UPDATE gisTemp SET idsap = (SELECT substring(codConsumidor from 4 for 10) FROM gisTemp WHERE id = contador) WHERE id = contador;
        END IF;
    /*CHECA codConsumidor, SE <= 18900 PEGA BTE E NÚMEROS*/ 
    ELSIF (SELECT CAST((SELECT substring(codConsumidor from 4 for 10) FROM gisTemp WHERE id = contador) AS integer)) <= 18900 THEN
        UPDATE gisTemp SET idsap = concat((SELECT substring(codConsumidor from 0 for 4) FROM gisTemp WHERE id = contador),(SELECT substring(codConsumidor from 6 for 10) FROM gisTemp WHERE id = contador)) WHERE id = contador;    
    END IF;
    EXCEPTION WHEN invalid_text_representation THEN
    ------ NÃO FAZ NADA
    END;

END IF;
    contador := contador+1;
EXIT WHEN contador >= maximoRegistros;
END LOOP;
RETURN 1;
END; $a$ LANGUAGE plpgsql;

当我在 java 中运行时,我得到这个错误:java.lang.OutOfMemoryError: GC 开销限制超出

    public boolean processaGISSAP() 
    CallableStatement cstmt = null;
    try 
        String sql = "call geracodigo()";
        cstmt = con.prepareCall(sql);
        cstmt.execute(sql);
     catch (SQLException ex) 
        Logger.getLogger(CircuitDAO.class.getName()).log(Level.SEVERE, null, ex);
    
    return true;

我认为这是因为在我的程序中有更新和选择,而 java 正在得到这些响应。

有什么方法可以从程序中获得最终响应?

【问题讨论】:

【参考方案1】:

当我使用单独的 BEGIN ... EXCEPTION .. END 部分创建这种嵌套函数调用时,我会使用不同的函数。在我看来,这至少使代码更易于维护和阅读(和调试)。

一般来说:您在代码末尾有一个带有测试的循环。它是一种方法,但总是有一个问题:如果它没有到达测试或更改测试值的代码行怎么办?然后它会永远循环,你会得到你描述的问题。 在您的代码中,您有几个异常处理程序。那时你什么都不做。但是,如果其中一个内部循环抛出异常怎么办?该值未更新,测试将无法正常执行。

通过这种循环,我将始终构建一个安全测试,以防止它像这样永远运行:

cntLoopMax integer:=10
cntLoop integer:=0;

LOOP
 BEGIN
   ...
 EXCEPTION
  cntLoop := cntLoop + 1;
 END
  if cntLoop >= cntLoopMax then
    raise notice 'exit because of cntLoop exceeds cntLoopMax';
    EXIT cntLoop>=cntLoopMax;
  end if;
  EXIT ...      
END LOOP

在您的代码中,我至少看到一个可能导致此问题的循环。这是第一个循环,其开头为: IF (quantidadeCaracteres)

【讨论】:

以上是关于存储过程 Postgres 和 Java的主要内容,如果未能解决你的问题,请参考以下文章

从 java 调用存储过程时出错

简单的更新集 postgres 存储过程

Postgres存储过程:如何使用out参数返回多条记录?

Node.js:如何在 Sequelize 中使用 Postgres 存储过程?

带参数的 Dapper Postgres 存储过程

postgres 使用存储过程批量插入数据