Java: 如何在Oracle数据库中调用存储过程

9

编辑:虽然此问题中的某些答案可能帮助其他人解决不同的问题,但实际上解决方案与数据库连接的自动提交功能存在一些错误有关!在执行查询后强制提交会导致数据库反映更改,因此下面显示的代码是调用此类型存储过程的正确方法。

我正在尝试调用Oracle数据库中的一个简单存储过程。

该过程如下所示:

procedure clear_orderProcDtlByOrdId(p_order_id in order_header.order_id%type,
                                    p_transaction_id in sl_order_processing_dtl.transaction_id%type DEFAULT NULL,
                                    p_item_action_id in sl_order_processing_dtl.item_action_id%type DEFAULT NULL )
...

我遇到的有问题的Java代码如下:
    try 
    {
        CallableStatement storedProc = conn.prepareCall("{call PKG_PI_FRAUD.clear_orderProcDtlByOrdId(?)}");
        storedProc.setString(1, orderID);
        storedProc.execute();
    } 
    catch (SQLException e) 
    {
        e.printStackTrace();
    }

我没有收到任何错误信息,但是数据库中没有反映出任何变化。当我在SQL Developer上运行该过程时,我可以看到结果。我认为这可能是提交问题,但我建立的连接处于自动提交模式。
非常感谢您的帮助!

订单ID在数据库中设置为VARCHAR类型吗? - PermGenError
@PremGenError:orderID 在数据库中是一个 VARCHAR2。 - aeros
2
@twoleggedhorse 这会导致一个 PLS-00707: 不支持的结构或内部错误 [2603] - aeros
@twoleggedhorse 是的,我是这样做的。 - aeros
connstoredProc 都没有使用 try-with-resources 自动关闭,也没有在 finally 块中显式调用 close() 方法来关闭。 - Awan Biru
显示剩余5条评论
2个回答

3

虽然此问题的一些答案可能会对其他不同问题有所帮助,但实际上解决方案与数据库连接的自动提交功能相关的某些错误有关!在执行查询后强制提交可以使数据库反映出更改,因此在问题中显示的代码是调用此类型存储过程的正确方式!


1
为了能够捕获Oracle数据库中的过程返回值,请尝试以下方法。
public static void main(String[] args) {

        try {

            Class.forName("oracle.jdbc.driver.OracleDriver");
            String url = "jdbc:oracle:thin:@localhost:1521:xe";
            Connection con = DriverManager.getConnection(url, db_user, password);
            System.out.println("Connected to database");

            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy");
            Date now = new java.sql.Date(simpleDateFormat.parse("12/02/2001").getTime());

            String command = "{call SALDOS(?,?)}";
            CallableStatement cstmt = con.prepareCall(command);
            cstmt.registerOutParameter(2, Types.DECIMAL);

            cstmt.setDate(1, now);
            cstmt.execute();
            Double str = cstmt.getDouble(2);

            cstmt.close();
            System.out.println("Retorno: " + str);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

如果您使用不同的Returns Map SimpleJdbcCall,则可以这样做:
    SimpleJdbcCall call = Util.getSimpleJdbcCallInstance();
    call.setProcedureName("PROCED_CONDOMINIAL");
    call.declareParameters(
            new SqlParameter("CONDOMINIO", Types.VARCHAR),
            new SqlParameter("BLOCO", Types.VARCHAR),,
            new SqlOutParameter("P_NUMERO", Types.NUMERIC),
            new SqlOutParameter("P_LOG", Types.VARCHAR));

    Map<String, Object> parametros = new HashMap<String, Object>();
    parametros.put("CONDOMINIO_IC", descricaoCondominio);
    parametros.put("BLOCO_IC", imovelCondominial.getBloco());

    Map<String, Object> out = call.execute(parametros);
    BigDecimal chave = (BigDecimal) out.get("P_NUMERO");
    imovelCondominial.setId(chave.longValue());

和过程的声明

create or replace PROCEDURE         PROCED_CONDOMINIAL
               (CONDOMINIO            VARCHAR2,
                BLOCO                 VARCHAR2,
                NUMERO                OUT NUMBER,
                LOG                   OUT VARCHAR2)      -- PARAMETROS DE SAIDAS (OUT).-

在这里工作过。看看这个博客。

http://jameajudo.blogspot.com.br/2009/03/call-procedure-oracle-with-java-and.html

在Oracle 10xe和11xe上进行了测试。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接