RECORD类型真的不兼容JDBC吗?驱动使用的是 OJDBC6.jar
Java代码:
dbStrategy.openConnection();
WrappedConnectionJDK6 wrapped = (WrappedConnectionJDK6) dbStrategy.getConnection();
OracleConnection oracleConnection = (OracleConnection) wrapped.getUnderlyingConnection();
CallableStatement callableStatement = oracleConnection.prepareCall("{call XXX_Info_Utl_Pkg.get_order_admin(?,?,?,?,?)}");
callableStatement.setInt(1, Integer.parseInt(orderNumber));
callableStatement.registerOutParameter(2, OracleTypes.ARRAY, "XXX_INFO_UTL_PKG.SEAGRS_ORDER_REC");
callableStatement.registerOutParameter(3, OracleTypes.NUMBER);
callableStatement.registerOutParameter(4, OracleTypes.VARCHAR);
callableStatement.registerOutParameter(5, OracleTypes.NUMBER);
和甲骨文代码:
PROCEDURE get_order_admin(
p_order_num_in IN NUMBER,
p_order_admin_out OUT XXX_info_utl_pkg.seagrs_order_rec,
p_error_code_out OUT PLS_INTEGER,
p_error_msg_out OUT VARCHAR2,
p_ret_status_out OUT PLS_INTEGER);
TYPE seagrs_order_rec
IS
record
(
order_admin VARCHAR2(10),
contact_name VARCHAR2(50),
contact_email_addr VARCHAR2(100),
contact_phone_num VARCHAR2(30));
这里面临的错误是 -
异常:名称模式无效:XXX_INFO_UTL_PKG.SEAGRS_ORDER_REC
记录类型与 JDBC 驱动程序不兼容:
Oracle JDBC驱动支持调用不可行 PL/SQL RECORD、BOOLEAN 或表的参数或返回值 具有非标量元素类型。但是,Oracle JDBC 驱动程序支持 标量元素类型的 PL/SQL 索引表。
虽然您不能直接使用 JDBC 来获取您的 PL/SQL RECORD 类型,但您可以编写一个匿名 PL/SQL 块并将记录返回到一个局部变量中,然后您可以在其各个属性中进行分解,如下所示:
DECLARE
rec XXX_info_utl_pkg.seagrs_order_rec;
BEGIN
get_order_admin(?, rec, ?, ?, ?);
? := rec.order_admin;
? := rec.contact_name;
? := rec.contact_email_addr;
? := rec.contact_phone_num;
END;
您现在可以使用以下 JDBC 代码调用过程:
try (CallableStatement s = con.prepareCall(" ... previous PL/SQL block ...")) {
s.setInt(1, Integer.parseInt(orderNumber));
// Ordinary out parameters
s.registerOutParameter(2, Types.NUMBER);
s.registerOutParameter(3, Types.VARCHAR);
s.registerOutParameter(4, Types.NUMBER);
// Out parameters from your decomposed record
s.registerOutParameter(5, Types.VARCHAR);
s.registerOutParameter(6, Types.VARCHAR);
s.registerOutParameter(7, Types.VARCHAR);
s.registerOutParameter(8, Types.VARCHAR);
s.execute();
// Now, retrieve all the out parameters
}
我最近在博客上更详细地介绍了这项技术。该博客文章还包含有关如何为所有具有记录 IN/OUT 参数的函数/过程自动生成匿名 PL/SQL 块的说明。
如果您不喜欢在 Java 代码中直接使用 pl/sql 块,还有一种使用 STRUCT 类型的方法。
例如,在您上面的代码中,将类型从数组更改为结构:-
dbStrategy.openConnection();
WrappedConnectionJDK6 wrapped = (WrappedConnectionJDK6) dbStrategy.getConnection();
OracleConnection oracleConnection = (OracleConnection) wrapped.getUnderlyingConnection();
CallableStatement callableStatement = oracleConnection.prepareCall("{call XXX_Info_Utl_Pkg.get_order_admin(?,?,?,?,?)}");
callableStatement.setInt(1, Integer.parseInt(orderNumber));
callableStatement.registerOutParameter(2, Types.STRUCT, "XXX_INFO_UTL_PKG.SEAGRS_ORDER_REC");
callableStatement.registerOutParameter(3, OracleTypes.NUMBER);
callableStatement.registerOutParameter(4, OracleTypes.VARCHAR);
callableStatement.registerOutParameter(5, OracleTypes.NUMBER);