在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
相关产品推荐
相关产品推荐

