4

I have a Java app accessing an oracle stored procedure. The arguments to the stored procedure include an array type. I do it like the following...

con = this._getConnection();  
Connection narrowdConn = (Connection)WSJdbcUtil.getNativeConnection( (WSJdbcConnection)con );  

callable = con.prepareCall("{call MY_PKG.MY_PROCEDURE(?, ?)}");  


ArrayDescriptor arrayDescriptor = ArrayDescriptor.createDescriptor("VARCHAR2_ARR", narrowdConn);  
ARRAY arrayArg1 = new ARRAY(arrayDescriptor, con, docNames);  
ARRAY arrayArg2 = new ARRAY(arrayDescriptor, con, docTypes);  

callable.setArray(1, arrayArg1);  
callable.setArray(2, arrayArg2);  

callable.execute();  

Now, I am getting this Exception...

java.sql.SQLException: invalid name pattern: MY_PKG.VARCHAR2_ARR

VARCHAR2_ARR is a public TYPE, defined inside an Oracle Package like the following:

TYPE VARCHAR2_ARR IS TABLE OF VARCHAR2(50);

And used as such in my stored proc...

PROCEDURE MY_PROCEDURE  
    (V_ARR_ARG1  IN VARCHAR2_ARR,  
     V_ARR_ARG2  IN VARCHAR2_ARR)  

3 Answers 3

1

the type VARCHAR2_ARR is a PLSQL type, you won't be able to interface it directly from java. I suggest you look into this thread on AskTom regarding a similar question.

Here are a couple suggestions:

  • create a SQL TYPE that you can bind from java
  • insert into a temporary table from java and read from it in plsql

In both cases you will have to either modify the PLSQL procedure or add a new translation procedure.

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

4 Comments

actually the problem is that any type created within a package is not visible by java. If I create the type at schema level then it works.
@Coder: PLSQL types can't be accessed directly from java. You will have to use a true SQL type (CREATE type...) and either a wrapper procedure with this SQL type or modify your procedure to accept the new type.
If I understand it correctly, if a type is declared inside a package it's called PLSQL type right? I am confused on how does jdbc succeed to make a call to a procedure declared and defined inside a package if calling a PLSQL type fails. What's the difference between the two?
It is similar to how you are able to call public method of a class in java , however no direct access to private member. Just an analogy , I know it is not the reason.
0

We need to set accessToUnderlyingConnectionAllowed falg true while creating a datasource

Comments

0

I did stuck at this problem. Hope this illustration might help you:

Steps to create the procedure in oracle.

  • Create type of the desired object as:
CREATE OR REPLACE TYPE STUDENT_TYPE IS OBJECT
( ID NUMBER,
  NAME VARCHAR2(50));
  • Create another object of array as:
CREATE OR REPLACE TYPE STUDENT_ARRAY IS TABLE OF STUDENT_TYPE;
  • Create procedure to accepting array of object and do the desired operation, I am here just inserting the entries in table as:
CREATE OR REPLACE PROCEDURE SP_INSERT_STUDENT_RECORD_IN_BULK(
IN_STUDENT_RECORDS STUDENT_ARRAY) IS
BEGIN 
  FOR i IN IN_STUDENT_RECORDS.first.. IN_STUDENT_RECORDS.last
   LOOP
    BEGIN 
      INSERT INTO STUDENT(ID,NAME) VALUES
      (IN_STUDENT_RECORDS(i).ID, IN_STUDENT_RECORDS(i).NAME)
    END;
   END LOOP:
END SP_INSERT_STUDENT_RECORD_IN_BULK;

Code snippet to call Procedure through Java

import org.springframework.jdbc.core.*;
import oracle.jdbc.OracleConnection;
....
List<Student> students = getStudentList();
try(Connection hikariCon = dataSource.getConnection()){
    if(hikariCon.isWrapperFor(OracleConnection.class)){
        OracleConnection con = hikariCon.unwrap(OracleConnection.class);
        Object[] students = students.stream().map(student -> {
            return con.createStruct(STUDENT_TYPE, new Object[]{
                student.getId(),
                student.getName()
            });
        }).collect(Collectors.list()).flatMap(List::stream).toArray();
        
        SimpleJdbcCall jdbcCall = new SimpleJdbcCall(dataSource)
                                .withProcedureName("SP_INSERT_STUDENT_RECORD_IN_BULK")
                                .declareParameters(
                                new SqlParameter("IN_STUDENT_RECORDS", Types.ARRAY));
        jdbcCall.execute(con.createOracleArray(STUDENT_ARRAY,students))
    }
} catch(Exception e){
    log.error("Error due to- {}",e,getMessage());
}

Comments

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.