2

I have a problem will calling plsql procedure from Java. Package with procedure is below: (schema job_runner and connection user/scheme is not same):

create or replace package  test_package_for_sp as

  type some_record_type is record
  (
      field_number      number,
      field_varchar2    varchar2 (128),
      field_date        date
  );

  type some_table_type is table of some_record_type;


  procedure proc_table (p_card_bin    in     varchar2,
                        p_date        in     date default null,
                        p_out_table      out some_table_type);
}

And then I try to call it from Java with callableStatement:

    final String typeTableList = "SOME_TABLE_TYPE";

    CallableStatement cs = null;
    try (Connection con = dataSource.getConnection()) {
        con.setSchema("JOB_RUNNER");

        cs = con.prepareCall("{call job_runner.test_package_for_sp.proc_table(?, ?, ?)}");

        cs.setString(1, "54867321");
        cs.setDate(2, Date.valueOf(ZonedDateTime.now().minusDays(200).toLocalDate()));
        cs.registerOutParameter(3, Types.ARRAY, typeTableList);

        cs.execute();
    } finally {
        if (cs != null)
            cs.close();
    }

Error raise:

java.sql.SQLException: invalid name pattern: <connection_scheme>.SOME_TABLE_TYPE

    at oracle.jdbc.oracore.OracleTypeADT.initMetadata11_2(OracleTypeADT.java:764)
    at oracle.jdbc.oracore.OracleTypeADT.initMetadata(OracleTypeADT.java:479)
    at oracle.jdbc.oracore.OracleTypeADT.init(OracleTypeADT.java:443)

If I change value in typeTableLis from value SOME_TABLE_TYPE to full path with package and scheme JOB_RUNNER.TEST_PACKAGE_FOR_SP.SOME_TABLE_TYPE exception change to:

java.sql.SQLSyntaxErrorException: ORA-01948: identifier's name length (35) exceeds maximum (30)
ORA-06512: at "SYS.DBMS_PICKLER", line 18
ORA-06512: at "SYS.DBMS_PICKLER", line 58
ORA-06512: at line 1


    at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:494)

Does anybody know how to call this procedure from java?

2
  • 1) Create your type as SQL type ("create type some_record_type as object (..);") 2) Use oracle java arraydescriptor, to identify and pass the type in your procedure; Commented Feb 6, 2019 at 11:52
  • @Ychdziu Arraydescriptor internally is called (at oracle.sql.ArrayDescriptor.createDescriptor(ArrayDescriptor.java:79)). And this class is deprecated. Could you past some example how to identify and pass type from arraydescriptor to procedure? Commented Feb 6, 2019 at 11:58

2 Answers 2

1

You can set the JDBC connection property "oracle.jdbc.createDescriptorUseCurrentSchemaForSchemaName" to "true", then switch the schema to "job_runner" (ALTER SESSION SET CURRENT_SCHEMA=job_runner) and use TEST_PACKAGE_FOR_SP.SOME_TABLE_TYP for typeTableList.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks to comment, but this same not working. Error is: java.sql.SQLException: invalid name pattern: TEST_PACKAGE_FOR_SP.SOME_TABLE_TYPE at oracle.jdbc.oracore.OracleTypeADT.initMetadata11_2(OracleTypeADT.java:764) at oracle.jdbc.oracore.OracleTypeADT.initMetadata(OracleTypeADT.java:479) at oracle.jdbc.oracore.OracleTypeADT.init(OracleTypeADT.java:443) at oracle.sql.ArrayDescriptor.initPickler(ArrayDescriptor.java:1499)
Which version of the driver are you using? 11.2 or 12.1 or 12.2? 18c maybe? Do java -jar ojdbcX.jar to find out.
driver version: 12.2.0.1
I suspect the database version is older than that (12.2) because the max length of an identifier in Oracle was extended from 30 to 128 in 12.2. What's your database version?
yes, oracle 11.2.0.4.0. Thanks, it seems to be related to this.
0

One of the approach:

package testproject;

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

import oracle.sql.ARRAY;

import oracle.jdbc.OracleCallableStatement;

import oracle.sql.ArrayDescriptor;

    public class MainClass {
    public MainClass() {
        super();
    }

    public static void main(String[] args) {
        MainClass mainClass = new MainClass();

        Connection conn = null;

        ArrayDescriptor des = null;

        try {

            Object[] obj1 = { 1, "2017-01-01 10:12:10", 200 };
            Object[] obj2 = { 2, "2017-06-01 10:12:10", 600 };
            Object[] obj3 = { 3, "2017-08-01 10:12:10", 990 };

            conn =
DriverManager.getConnection("jdbc:oracle:thin:@<DB_HOST>",
                            "<user>", "<pass>");

          try {
              des = ArrayDescriptor.createDescriptor("AJ_TEST_OBJ_TBL", conn);
          } catch (SQLException e) {
              System.out.println("Arraydesc went wrong.");
              System.out.println(e.getStackTrace());
          }

          ARRAY nArray =
              new ARRAY(des, conn, new Object[] { obj1, obj2, obj3 });

            OracleCallableStatement pstmt =
                (OracleCallableStatement)conn.prepareCall("begin 
aj_test_array_pck.print_tbl_parameters(?,?); end;");

            pstmt.setArray(1, nArray);
            pstmt.registerOutParameter(2, Types.VARCHAR);
            pstmt.execute();

            String status = pstmt.getString(2);
            System.out.println("Status: " + status);

            pstmt.close();
            conn.close();
        } catch (SQLException e) {
            System.out.println("Oops with select");
            System.out.println(e.getStackTrace());
        } catch (ClassNotFoundException e) {
            System.out.println("Oops with class");
        }
    }

}

where "AJ_TEST_OBJ_TBL" is a SQL type object.

4 Comments

Yes, I saw this example somethere, but it has example with IN array param, not OUT as I needed.
And as I say before, ArrayDescriptor.createDescriptor has been called internally
The in parameter is the defined array, the out is just a simple varchar, with outcomes E/S, just to see, if the procedure did its job.
The main aspect is, to define your type not as a PL/SQL type, but as a SQL type.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.