java - 如何在 PL/SQL 中返回 ROWTYPE 并在 Java 中检索它?

标签 java oracle stored-procedures jdbc plsql

我有一个 PL/SQL 函数,它返回 ROWTYPE。我需要从 Java 调用这个函数并检索数据(作为数组、映射、结构、类,无论如何,我真的不在乎,我只需要它,最好不需要搞乱 PL/SQL代码,例如更改函数的返回类型)。我研究了多个“解决方案”和论坛,但没有找到答案。 我已经尝试将 out 参数注册为结构体和类,但没有成功。 这是我的 PL/SQL 函数:

  FUNCTION DAR_CLIENTE(cedula VARCHAR2) RETURN CLIENTE%ROWTYPE AS
  RET CLIENTE%ROWTYPE;
  BEGIN
    -- TAREA: Se necesita implantación para FUNCTION P_CLIENTE.DAR_CLIENTE
    SELECT * INTO RET FROM CLIENTE WHERE Persona_cedula=cedula;
    RETURN RET;
  END DAR_CLIENTE;

这是我的java代码:

public static void main(String args[]) throws SQLException {
    Properties info = new Properties();
    info.put(OracleConnection.CONNECTION_PROPERTY_USER_NAME, DB_USER);
    info.put(OracleConnection.CONNECTION_PROPERTY_PASSWORD, DB_PASSWORD);
    info.put(OracleConnection.CONNECTION_PROPERTY_DEFAULT_ROW_PREFETCH, "20");

    OracleDataSource ods = new OracleDataSource();
    ods.setURL(DB_URL);
    ods.setConnectionProperties(info);

    // With AutoCloseable, the connection is closed automatically.
    try (OracleConnection connection = (OracleConnection) ods.getConnection()) {
        // Get the JDBC driver name and version
        DatabaseMetaData dbmd = connection.getMetaData();
        System.out.println("Driver Name: " + dbmd.getDriverName());
        System.out.println("Driver Version: " + dbmd.getDriverVersion());
        // Print some connection properties
        System.out.println("Default Row Prefetch Value is: " + connection.getDefaultRowPrefetch());
        System.out.println("Database Username is: " + connection.getUserName());
        System.out.println();
        System.out.println(connection.getSchema());
        // Perform a database operation

        Map<String, Class<?>> myMap = new HashMap<String, Class<?>>();
        myMap.put("P09551_1_5.CLIENTE", Cliente.class);

        connection.setTypeMap(myMap);
        CallableStatement storedProc = connection
                .prepareCall("{? = call P09551_1_5.p_cliente.dar_cliente('1144102435')}");

        storedProc.registerOutParameter(1, oracle.jdbc.OracleTypes.JAVA_STRUCT);
        storedProc.execute();

    }
}

我正在使用ojdbc8.jar。

此信息在程序启动时打印到控制台:

Driver Name: Oracle JDBC driver
Driver Version: 18.3.0.0.0

最佳答案

我通过将返回类型更改为 SYS_REFCURSOR 解决了该问题,如下所示:

FUNCTION DAR_CLIENTE(cedula VARCHAR2) RETURN SYS_REFCURSOR AS
  RET SYS_REFCURSOR;
  BEGIN
    -- TAREA: Se necesita implantación para FUNCTION P_CLIENTE.DAR_CLIENTE
    OPEN RET FOR
    SELECT * FROM CLIENTE WHERE Persona_cedula=cedula;
    RETURN RET;
  END DAR_CLIENTE;

Java代码如下:

public static void main(String args[]) throws SQLException {
    Properties info = new Properties();
    info.put(OracleConnection.CONNECTION_PROPERTY_USER_NAME, DB_USER);
    info.put(OracleConnection.CONNECTION_PROPERTY_PASSWORD, DB_PASSWORD);
    info.put(OracleConnection.CONNECTION_PROPERTY_DEFAULT_ROW_PREFETCH, "20");

    OracleDataSource ods = new OracleDataSource();
    ods.setURL(DB_URL);
    ods.setConnectionProperties(info);

    // With AutoCloseable, the connection is closed automatically.
    try (OracleConnection connection = (OracleConnection) ods.getConnection()) {
        // Get the JDBC driver name and version
        DatabaseMetaData dbmd = connection.getMetaData();
        System.out.println("Driver Name: " + dbmd.getDriverName());
        System.out.println("Driver Version: " + dbmd.getDriverVersion());
        // Print some connection properties
        System.out.println("Default Row Prefetch Value is: " + connection.getDefaultRowPrefetch());
        System.out.println("Database Username is: " + connection.getUserName());
        System.out.println("Schema: "+connection.getSchema());
        System.out.println();
        // Perform a database operation

        Map<String, Class<?>> myMap = new HashMap<String, Class<?>>();
        myMap.put("P09551_1_5.CLIENTE", Cliente.class);

        connection.setTypeMap(myMap);
        CallableStatement storedProc = connection
                .prepareCall("{? = call P09551_1_5.p_cliente.dar_cliente('1144102435')}");

        storedProc.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);
        storedProc.execute();
        ResultSet resultSet = (ResultSet) storedProc.getObject(1);
        ResultSetMetaData meta = resultSet.getMetaData();
        int columnCount = meta.getColumnCount();
        while (resultSet.next()) {
            for (int i = 1; i <= columnCount; i++) {
                System.out.println(meta.getColumnLabel(i)+":"+resultSet.getObject(i).toString());
            }
            //System.out.println(resultSet.getString(1));

        }

    }
}

在控制台上获取此响应(我这样做是为了所有字段都将打印其列标签,尽管这个特定的表只有一列):

Driver Name: Oracle JDBC driver
Driver Version: 18.3.0.0.0
Default Row Prefetch Value is: 20
Database Username is: P09551_1_5
Schema: P09551_1_5

PERSONA_CEDULA:1144102435

解决方案的来源如下: https://www.mkyong.com/jdbc/jdbc-callablestatement-stored-procedure-cursor-example/

关于java - 如何在 PL/SQL 中返回 ROWTYPE 并在 Java 中检索它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58896962/

相关文章:

java - JDBC-ORA-00984 : column not allowed here

oracle - 将规范和正文导出到单个文件中

sql-server - 嵌套的插入exec解决

SQL 作业状态

performance - 有没有工具来加载测试 PLSQL

java - 在大文件中查找重复项和排列

Java:读取未知数量的属性

java - Java 中 Class<...> 的使用

Oracle 约束和空值

c# - SQL Server 中是否有 Oracle 数组绑定(bind)的等效功能?