Retrieving a 2d varray in Java with JDBC - java

I have the following types:
create or replace TYPE mytimestamp AS VARRAY(300) OF TIMESTAMP(6);
create or replace TYPE trade_history_dts_array AS VARRAY(300) OF mytimestamp;
The types are used in this way in the stored procedure:
trade_history_dts tradehistorydtsarray ;
FOR i IN 1..20
loop
trade_history_dts(i) := mytimestamp();
LOOP
trade_history_dts(i).extend();
FETCH trade_history_cursor INTO
trade_history_dts(i)(j),
dbms_output.put_line(trade_history_dts(i)(j));
j := j+1;
exit when trade_history_cursor%notfound;
END LOOP;
j:=1;
end loop;
The stored procedure is tested, and I can get the right the result:
information for trade 1
trade_history_dts(1)(1)17-OCT-05 03.49.57.000000 PM
trade_history_dts(1)(2)17-OCT-05 03.49.58.000000 PM
information for trade 2
trade_history_dts(2)(1)27-JUN-05 09.02.59.000000 AM
trade_history_dts(2)(2)27-JUN-05 09.02.59.000000 AM
trade_history_dts(2)(3)27-JUN-05 09.03.01.000000 AM
information for trade 3
trade_history_dts(3)(1)09-FEB-06 09.31.03.000000 AM
trade_history_dts(3)(2)09-FEB-06 09.31.05.000000 AM
....
Now I want to get the this result in java, and transform it to a 2-dimensional array.
I tried the following:
Timestamp[][] trade_history_dts = (Timestamp[][])trade_history_dts_arr.getArray();
but it does not work. Does anybody know how to transform it to a 2-dimensional array in java? Thank you!

The approach that you've adopted will not work, because JDBC on it's own does not have any support for Oracle's collection types. You'll need to work on objects of type contained in the Oracle JDBC driver for accessing the contents of the resultset in the manner that you desire. This would involve casting the ResultSet object into an OracleResultSet so that the inner elements of the collection can be accessed via instances of oracle.sql.ARRAY elements.
You could also read an Object from the ResultSet using the getObject method, and then cast it into the oracle.sql.ARRAY instance which represents the collection. Details on this mechanism, can be found in the Oracle Database JDBC Developer's Guide and Reference.
Additionally, you'll need to parse each element in the result set,and process them in a similar manner, for you are returning a multi-level collection. Details for this are provided in the same guide in a separate section.

Related

Retrieving data from associative array of custom object type from Oracle DB using CallableStatement

Summary
I am calling a stored procedure(SP) in an Oracle 12c database from a Spring-boot application. I am using CallableStatement to do this. One of the OUT parameters of the SP is an associative array with elements of a custom object type. I am having trouble retrieving the data in a proper method.
Code
TYPE trans_list IS TABLE OF T_RPT_TXN_DTLS_OBJ INDEX BY PLS_INTEGER;
TYPE T_RPT_TXN_DTLS_OBJ AS OBJECT( id VARCHAR2(20), amount NUMBER(10,2), desc VARCHAR2(100))
Connection connection = jdbcTemplate.getDataSource().getConnection();
OracleCallableStatement callableStatement = connection.prepareCall("{call SAMPLE_PROC(?,?)}").unwrap(OracleCallableStatement.class);
callableStatement.setString(1, ID);
--Here I don't know what to do--
callableStatement.registerIndexTableOutParameter(2, 500, OracleTypes.OTHER, 0);
--------------------------------
Things I have tried
I looked through different websites using google. Went through stackoverflow as well. The above code is where I am stuck at. Since the 3rd argument is the datatype of the array elements, I put in OracleTypes.OTHER but that throws an SQLException: invalid column type 1111.
I read in the official docs that for custom object types, we can map them to Java objects. I have no idea how to do that either. Please refer to User_defined types in https://docs.oracle.com/cd/B19306_01/java.102/b14355/datacc.htm#BHCGCBJC
What I am asking in brief
Any sample code, detailed docmentation, links to online examples that fits my case. I specifically need to know arg[2] of the out parameter registration, and how I might go about mapping to a custom Java object from the callableStatement (perhaps using .getObject(int) but I don't know about the mapping).
See this answer.
You cannot.
You need to define the data type in the SQL scope (using CREATE TYPE) rather than in the PL/SQL scope, in a package as JDBC can only work with SQL defined data types.
A consequence of point 1 is that JDBC does not support associative arrays, as they are a PL/SQL only data type, and you need to use collections (unlike C#, which only supports associative arrays and does not support collections). So you need to remove the INDEX BY clause from the type.
You need to be able to map from the type in the array to a Java data structure; one way of doing this is to use the SQLData interface. An example is in this answer.
Define:
callableStatement.registerOutParameter(2, OracleTypes.ARRAY,"trans_list");
Call proc:
callableStatement.executeUpdate();
Then get out parameter as
java.sql.Array array = callableStatement.getArray(2);
Object outputParamValue = array.getArray();
Type Caste outputParamValue if needed.

Dynamic Oracle Type not visible in Java

I have an oracle function that I use to update some data into the database from Java.
The Function:
FUNCTION addFunc (
contact_id IN NUMBER,
contact_distrib_list IN contact_array
)
RETURN VARCHAR2;
The array type is declared in the package as
TYPE contact_array IS TABLE OF VARCHAR2(100) INDEX BY BINARY_INTEGER;
Now,
I am trying to call this Function from my Java code.
ArrayDescriptor arrayDescriptor = ArrayDescriptor.createDescriptor("contact_array", sqlConnection);
But, when i try to do the above it complains that the type is not recognized.
java.sql.SQLException: invalid name pattern: contact_array
I tried all the ways to supply a sql name here. I tried the schema name.package name.array name etc. But still the same error.
Am I incorrectly defining the type in oracle?
Is there any other way of connecting using Java JDBC?
If you want to pass a PL/SQL index-by table (also known as an associative array) to a stored procedure, you will need to use Oracle extensions to JDBC. You cannot use ArrayDescriptor with index-by tables.
In particular, you will need to use the OracleCallableStatement.setPlsqlIndexTable method, for example:
((OracleCallableStatement)callableStatement).setPlsqlIndexTable(
3, data, data.length, data.length, Types.VARCHAR, 100);
I'm assuming that the index-by table is parameter number 3 and that data contains the array of Strings you wish to pass as the contents of the table. The number 100 is the length of the elements within the collection.

ActiveJDBC: integer[] on PostgreSQL with multiple schemas in one DB

I am trying to use ActiveJDBC to properly convert an integer[] from my PostgreSQL database into the java equivalent int[]. I get the fetch done properly, but the object that is returned is weblogic.jdbc.wrapper.Array_org_postgresql_jdbc_PgArray. I have yet to find a way to convert that.
I have tried 2 different ways of accessing the data:
First, using the standard record.findFirst("id = ?", id) format. Because I have multiple schemas in my database, I added the #Table notation to my Model.
Second, I tried doing a record.findBySQL("select array from record where id = ?", id). I also tried array::integer[].
Each time I get back the PgArray type. I have searched for a way to convert this type into something else for use, but nothing has worked.
Is there a way to do this? Do I need to use a different way of data retrieval other than ActiveJDBC?
JDBC defines java.sql.Array to handle array typed columns. PgArray is just the Postgres implementation of java.sql.Array.
Given the array object a you can call (Integer[])a.getArray() to get an Integer array from the JDBC array object (if the JDBC driver has decided that it will return you Integer objects and not some other Numbers). A helper method to extract the value and convert to int[] would probably be a good idea.
Don't know if activejdbc has support to do this conversion behind the scenes.

How to avoid use of oracle.sql.StructDescriptor and oracle.sql.STRUCT statement in java code?

How can we map PL/SQL type object and java object by avoiding use of oracle.sql.StructDescriptor and oracle.sql.STRUCT statements.
As i search on many sites, even JPA also internally use StructDescriptor and STRUCT to map SQL type and java objects. I don't want to go for hibernate framework.Is it any alternative provided in java?

How to pass Arraylist of Objects to a Procedure using spring mybatis

I want to pass an Arraylist of Objects for e.g.
Arraylist <SomeObject> listOFSomeObject
Where SomeObject is having two attributes key and value.
On DB side i have a table type of variable i.e.
create or replace type tableTypeVariable is table of SomeType;
CREATE OR REPLACE TYPE SomeTypeAS OBJECT
(key VARCHAR2(50),value VARCHAR2(50))
Now i want to map my each object of type SomeObject from a listOFSomeObject to the tableTypeVariable.
Can any body help me with that ?
Convert your ArrayList to an Array using toArray(), and pass it in as described here, How do you write arrays to an Oracle 10g XE db using iBatis?
Note that this a partial answer, it has nothing to do with mybatis. It could well be the case that mybatis won't support this and you'll have to fall back to plain JDBC. In this case this answer may be useful for you.
As far as I remember you cannot do this with plain JDBC, you'll need to use the Oracle driver.
For the custom type refer to this:
http://download.oracle.com/docs/cd/B13789_01/java.101/b10979/oraoot.htm#g1104293
For passing collections, refer to this:
http://asktom.oracle.com/pls/asktom/f?p=100:11:3714089787721267::::P11_QUESTION_ID:712625135727

Categories

Resources