【问题标题】:Invoking Stored Procedure from OracleJDBC giving exceptions从 OracleJDBC 调用存储过程给出异常
【发布时间】:2023-03-09 12:33:01
【问题描述】:

我正在尝试使用 Oracle JDBC 调用 Oracle 的存储过程。

我对 Oracle 很陌生,因此很难弄清楚如何调用 SP 并获得正确的输出。

下面的存储过程应该只给我 4 个没有输入的输出。

代码 sn-p 是:

cStmt=connection.prepareCall(" {call userName.user(?)}");               
                    cStmt.registerOutParameter(1, OracleTypes.CURSOR);

                    cStmt.executeUpdate();                  

                    rst = (ResultSet) cStmt.getObject(1);
                    while (rst.next()) {
                        int id = rst.getInt(1);
                        int Id1=rst.getInt(2);
                        String accoutNum=rst.getString(3);
                        String accountName=rst.getString(4);
                        System.out.println("valeus");
                        System.out.println(id);
                        System.out.println(Id1);
                        System.out.println(accoutNum);
                        System.out.println(accountName);
                    }

现在运行此代码给我以下错误:

java.sql.SQLException: ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'user'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

        at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
        at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
        at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879)
        at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:505)
        at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:223)
        at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
        at oracle.jdbc.driver.T4CCallableStatement.doOall8(T4CCallableStatement.java:204)
        at oracle.jdbc.driver.T4CCallableStatement.executeForRows(T4CCallableStatement.java:1041)
        at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1328)
        at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3593)
        at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3674)
        at oracle.jdbc.driver.OracleCallableStatement.executeUpdate(OracleCallableStatement.java:4780)
        at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1354)
        at demo.Oracle.main(Oracle.java:101)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)

我确信语法肯定存在问题。我用谷歌搜索了很多,但我找不到具体的解决方案..

谁能指导我.. JDBC jar 版本是 6.0

程序的标题是:

create or replace
procedure user is 
cursor user_cursor is select * from user_master;
v_rec_user user_cursor%rowtype;

【问题讨论】:

  • 能否请您发布存储过程的标题?
  • @StefanBeike 请查看编辑。在末尾添加标题。

标签: java database oracle stored-procedures jdbc


【解决方案1】:

您的过程定义没有参数;按照您的称呼方式,您期望它具有sys_refcursor, or a schema-level cursor type 类型的 OUT 参数。

我想你想要这样的东西:

create or replace procedure user(result out sys_refcursor) is
begin
    open result for
        select * from user_master;
end;
/

但由于您只展示了开头,因此不清楚您使用v_rec_cursor 的目的。

(另外,user 不是该过程的好名称,因为它是一个保留字;也许像 get_users 这样的名称会更好?)


调用该过程并打印结果的小型 Java 程序;这将为我编译并运行(* 替换为真实的数据库连接详细信息):

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

import oracle.jdbc.OracleTypes;
import oracle.jdbc.pool.OracleDataSource;

public final class DBTest
{
    public static void main(String[] args)
    throws SQLException
    {
        OracleDataSource datasource;
        Connection conn = null;
        CallableStatement cStmt = null;
        ResultSet rSet = null;

        try
        {
            datasource = new OracleDataSource();
            String jdbcURL = "jdbc:oracle:thin:*/*@*:1521:*";
            datasource.setURL(jdbcURL);
            conn = datasource.getConnection();
            cStmt = conn.prepareCall("{ call get_user(?) }");
            cStmt.registerOutParameter(1, OracleTypes.CURSOR);
            cStmt.execute();
            rSet = (ResultSet) cStmt.getObject(1);
            while (rSet.next())
            {
                System.out.println(rSet.getInt(1)
                    + ":" + rSet.getInt(2)
                    + ":" + rSet.getString(3)
                    + ":" + rSet.getString(4));
            }
        }
        finally
        {
            if (rSet != null)
            {
                rSet.close();
            }
            if (cStmt != null)
            {
                cStmt.close();
            }
            if (conn != null)
            {
                conn.close();
            }
        }
    }
}

【讨论】:

  • 按照你的建议做了。至少上述错误不会出现。但是结果集为空。当我尝试执行 cStmt.registerOutParameter(1, OracleTypes.CURSOR); 时出现空指针异常;我想我很接近了。你能帮忙吗?
  • @AngelsandDemons - 该语句中的 NPE 与结果集无关,你没有那么公平。 cStmt 为空很奇怪,你能在你的代码中验证吗?其他想法...您可能想使用execute() 代替executeUpdate(),并使用getCursor() 代替getObject(),但您似乎又没有达到这些目标。
  • 我只使用 execute()。 cStmt 不为空。但是我不明白你想让我在哪里写 getCursor()。 cStmt.getCursor() 未定义。你能指导我吗?
  • @AngelsandDemons - 好的,我通常使用OracleCallableStatment,它有getCursor;如果您使用CallableStatementgetObject 很好。那么如果cStmt 不为空,NPE 发生在哪里?
  • @AngelsandDemons - 我添加了一个简单的 Java 程序来调用您的程序。我不确定你在做什么不同。
猜你喜欢
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 2011-09-14
  • 1970-01-01
  • 2012-03-05
  • 1970-01-01
  • 2020-03-21
  • 1970-01-01
相关资源
最近更新 更多