You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Java中调用返回Boolean类型的PLSQL函数的正确方法

解决Java调用返回BOOLEAN类型的PL/SQL函数的问题

你当前的代码存在一个关键问题:Oracle JDBC驱动不支持直接映射PL/SQL特有的BOOLEAN类型,所以你用Types.BOOLEAN注册返回值和调用getBoolean(1)都会抛出SQL异常——这是因为BOOLEAN是PL/SQL的专属类型,不属于标准SQL类型。

下面给你两种可行的解决方案,根据你的实际场景选择:


方案一:修改PL/SQL函数为返回NUMBER类型(推荐)

这是兼容性最好的方案,把PL/SQL函数的返回值从BOOLEAN改成NUMBER,用1代表true,0代表false,这样Java端可以直接用标准JDBC类型处理。

修改后的PL/SQL函数

CREATE OR REPLACE FUNCTION get_details(
    I_emp_id IN NUMBER,
    O_first_name OUT VARCHAR2,
    O_last_name OUT VARCHAR2,
    O_hire_date OUT DATE,
    O_error_message OUT varchar2
) return NUMBER IS
    CURSOR c_emp_info IS 
        select first_name, last_name, hire_date 
        from employees 
        where employee_id = I_emp_id;
begin
    open c_emp_info;
    fetch c_emp_info into O_first_name, O_last_name, O_hire_date;
    close c_emp_info;
    return 1; -- 1表示执行成功
exception
    when others then
        O_error_message := substr(sqlerrm,1,100);
        return 0; -- 0表示执行失败
end;
/

对应的Java代码修正

package com.jdbcjava.examples;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Types;

public class JDBCCallOracleFunction {
    private static final String DB_DRIVER="jdbc:oracle:thin:@//localhost:1521/orcl";
    private static final String DB_USER="hr";
    private static final String DB_PASSWD="hr";

    public static void main(String[] args){
        callFunctionOUTparameter();
    }

    private static void callFunctionOUTparameter(){
        // 使用try-with-resources自动关闭连接和Statement,避免资源泄漏
        try(Connection dbconnection = getDBConnection();
            CallableStatement mystmt = dbconnection.prepareCall("{?= call get_details(?,?,?,?,?) }")) {
            
            // 注册返回值为INTEGER类型,对应PL/SQL的NUMBER
            mystmt.registerOutParameter(1, Types.INTEGER);
            mystmt.setInt(2, 100);
            
            // 注册输出参数
            mystmt.registerOutParameter(3, Types.VARCHAR);
            mystmt.registerOutParameter(4, Types.VARCHAR);
            mystmt.registerOutParameter(5, Types.DATE);
            mystmt.registerOutParameter(6, Types.VARCHAR);
            
            mystmt.execute();
            
            // 判断执行结果
            boolean isSuccess = mystmt.getInt(1) == 1;
            System.out.println("函数执行是否成功:" + isSuccess);
            
            if(isSuccess){
                System.out.println("员工名:" + mystmt.getString(3));
                System.out.println("员工姓:" + mystmt.getString(4));
                System.out.println("雇佣日期:" + mystmt.getDate(5));
            } else {
                // 失败时获取错误信息
                System.out.println("错误信息:" + mystmt.getString(6));
            }
            
        } catch(SQLException e){
            e.printStackTrace();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    private static Connection getDBConnection() throws Exception{
        return DriverManager.getConnection(DB_DRIVER, DB_USER, DB_PASSWD);
    }
}

方案二:不修改PL/SQL函数,使用Oracle JDBC扩展API

如果你无法修改PL/SQL函数,可以使用Oracle提供的特定JDBC类OracleCallableStatement,并使用OracleTypes.PLSQL_BOOLEAN来处理PL/SQL的BOOLEAN类型。

修正后的Java代码

package com.jdbcjava.examples;

import oracle.jdbc.OracleCallableStatement;
import oracle.jdbc.OracleTypes;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Types;

public class JDBCCallOracleFunction {
    private static final String DB_DRIVER="jdbc:oracle:thin:@//localhost:1521/orcl";
    private static final String DB_USER="hr";
    private static final String DB_PASSWD="hr";

    public static void main(String[] args){
        callFunctionOUTparameter();
    }

    private static void callFunctionOUTparameter(){
        try(Connection dbconnection = getDBConnection();
            // 强制转换为OracleCallableStatement
            OracleCallableStatement mystmt = (OracleCallableStatement) dbconnection.prepareCall("{?= call get_details(?,?,?,?,?) }")) {
            
            // 使用Oracle特定的PLSQL_BOOLEAN类型注册返回值
            mystmt.registerOutParameter(1, OracleTypes.PLSQL_BOOLEAN);
            mystmt.setInt(2, 100);
            
            mystmt.registerOutParameter(3, Types.VARCHAR);
            mystmt.registerOutParameter(4, Types.VARCHAR);
            mystmt.registerOutParameter(5, Types.DATE);
            mystmt.registerOutParameter(6, Types.VARCHAR);
            
            mystmt.execute();
            
            // 直接获取BOOLEAN类型返回值
            boolean isSuccess = mystmt.getBoolean(1);
            System.out.println("函数执行是否成功:" + isSuccess);
            
            if(isSuccess){
                System.out.println("员工名:" + mystmt.getString(3));
                System.out.println("员工姓:" + mystmt.getString(4));
                System.out.println("雇佣日期:" + mystmt.getDate(5));
            } else {
                System.out.println("错误信息:" + mystmt.getString(6));
            }
            
        } catch(SQLException e){
            e.printStackTrace();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    private static Connection getDBConnection() throws Exception{
        return DriverManager.getConnection(DB_DRIVER, DB_USER, DB_PASSWD);
    }
}

注意事项

  • 这种方式需要你的项目中引入Oracle官方JDBC驱动(比如ojdbc8.jar,版本要和Oracle数据库匹配)。
  • 代码会和Oracle数据库耦合,失去跨数据库的兼容性,如果你的应用可能切换到其他数据库,不推荐使用。

内容的提问来源于stack exchange,提问作者redsoxlost

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:11:35