将对象类型传递给Oracle存储过程会出现“无效的名称模式”错误

时间:2015-05-14 14:12:40

标签: java oracle jdbc oracle11g oracle-sqldeveloper

Oracle数据库管理员为我提供了一个存储过程。它需要(IN)varchar并提供RECORD类型。记录类型如下:

TYPE BAL_RECORD_TYPE IS RECORD
(
  ac_no               VARCHAR2 (50),
  Account_type        VARCHAR2 (50),
  ac_status           VARCHAR2 (10),
  cur_code            VARCHAR2 (5),
  available_balance   NUMBER
);

我已按照以下链接在我的jdbc应用程序中支持RECORD类型。     http://betteratoracle.com/posts/31-passing-record-types-between-oracle-and-java

从上面的文章我改变了

stmt.registerOutParameter(2, OracleTypes.STRUCT, "RECTYPE");

stmt.registerOutParameter(2, OracleTypes.STRUCT, "BAL_RECORD_TYPE");

因为BAL_RECORD_TYPE是我的RECORD名字。

但我收到以下错误:

invalid name pattern: APPADMIN.BAL_RECORD_TYPE

这里APPADMIN是数据库的用户名。我不知道它是如何与OUT参数绑定的。

我的问题是:

  1. 我可以遵循哪些好的示例代码来支持oracle的RECORD类型?

  2. 错误的可能原因是什么(名称模式无效:APPADMIN.BAL_RECORD_TYPE)?

  3. 添加:

    1. 为我的oracle数据库管理员实现CURSOR类型而不是RECORD类型有多难?

2 个答案:

答案 0 :(得分:0)

我发现了这个问题。实际上,这不是我的意思。我们的oracle DB管理员定义了无法从JAVA访问的包内部类型。

以下是摘录: 我们不能调用在ORACLE中的包内定义的类型。 Java无法访问此类型,但sqlplus可以访问。因此,我们的DB管理员最终定义了包外的类型。

我从这里找到了这个解决方案:

http://forum.spring.io/forum/spring-projects/data/34668-array-as-out-parameter-java-sql-sqlexception-ora-06550-line-1-column-7

答案 1 :(得分:0)

不幸的是,您无法将PL / SQL RECORD类型传递给存储过程,也不能直接从存储过程中获取它。但你可以在这里使用这个技巧来解决这个限制:

DELARE
  rec APPADMIN.BAL_RECORD_TYPE;
BEGIN
  my_proc(some_input, rec);
  ? := rec.ac_no;
  ? := rec.account_type;
  ? := rec.ac_status;
  ? := rec.cur_code;
  ? := rec.available_balance;
END;

您现在可以按如下方式调用您的程序:

try (CallableStatement s = con.prepareCall(" ... above PL/SQL code ...")) {

    // Register each of your record's individual attribute types:
    s.registerOutParameter(1, Types.VARCHAR);
    s.registerOutParameter(2, Types.VARCHAR);
    s.registerOutParameter(3, Types.VARCHAR);
    s.registerOutParameter(4, Types.VARCHAR);
    s.registerOutParameter(5, Types.NUMERIC);

    s.execute();

    // Fetch each of your record's individual attribute types:
    String acNo = s.getString(1);
    String accountType = s.getString(1);
    String acStatus = s.getString(1);
    String curCode = s.getString(1);
    BigDecimal availableBalance = s.getBigDecimal(1);
}

I've recently blogged about this technique more in detail。如果您有许多程序/函数采用RECORD类型的IN / OUT参数,博客文章还包含有关如何自动执行此技术的更多信息。