How would you convert a java.util.List<String> instance into a java.sql.Array?
Use connection.createArrayOf(...)
For example:
final String[] data = yourList.toArray(new String[yourList.size()]);
final java.sql.Array sqlArray = connection.createArrayOf(typeName, data);
statement.setArray(position, sqlArray);
Where typeName is:
the SQL name of the type the elements of the array map to. The typeName is a database-specific name which may be the name of a built-in type, a user-defined type or a standard SQL type supported by this database. This is the value returned by Array.getBaseTypeName
As noted in the comments, this is Java 1.6. For older versions you can't create this in a driver-independent way. You are only supposed to get arrays, not create them. If you want to, you can instantiate the implementing class from your jdbc driver, but this is non-portable.
The type argument to createArrayOf is the element type, not the array type, so you probably want something like "varchar" or "text". VARIADIC is a function argument modifier, not a type specifier.
Related
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.
I am working with JDBC template(SPRING) which wrraps JDBC. during runtime all my variables values (bind variables) are held as strings(with some recognition of their actual type: bigint\varchar etc.).
While I'm using setObject, I'm not sure if I need to cast the variable value to it's real type or I can send the variable as string to setObject and the database will convert it according to the column name in the database(i.e. if it is compared with BigInt then it will convert the string to big int and then query and etc.)
Thanks,
If I am understanding your question correctly then I think you CAN NOT use setObject to pass a String that will be converted to a non-String SQL type (int, bigint).
Look at this question. Below is the answer from that question.
It is not the job of setObject to determine the correct conversion to the
column type. The setObject javadoc says, "The JDBC specification
specifies a standard mapping from Java Object types to SQL types. The
given argument will be converted to the corresponding SQL type before
being sent to the database." So it is solely looking at the Java type of
the object passed to it and converting that to a SQL type. So you pass it
a String and it converts it to a varchar which is appropriate. If you
want setObject to do a conversion to a different type, that is the reason
for the additional setObject variant which takes a target sql type to
convert to, but that doesn't help your situation where you don't know what
the target type is.
this question is very easystest-specific (but i don't know a better place to ask).
Is there a way to use parameters of type Array or List? Is there probably a separator character that could be used like this (excel table):
testMethod doubleList stringList
3.5,3.4,6.7 a,b,c
(the separator char is here ',')So that i get two paramters List doublelist and List stringList.
At the moment i do this by hand: using all as String parameter and "split" them on ','. and then converting the single strings to desired type.
Is there a "easier" way with easytest?
You simply use ':' as a delimiter and EasyTest splits up the string into a collection for you.
The javadoc of the #Param annotation in EasyTest says:
"If you want to pass a Collection type, then EasyTest framework provides the functionality to instantiate the Collection class for you and pass in the right generic parameter if possible. For eg. if you have a test method like this :
#Test
public void testArrayList(#Param(name="items") ArrayList<ItemId> items){
Assert.assertNotNull(items);
for(ItemId item : items){
System.out.println("testArrayList : "+item);
}
}
then all you have to do is :
pass the list of itemIds as ":" separated list in the test data file(XML, CSV,Excel or custom), for eg: 23:56:908:666
and register an editor or converter for converting the String data to object.
In case the generic type argument to the Collection is a standard Java type(Date, Character, Timestamp, Long, Interger, Float, Double etc) then you don't have to do anything and the framework will take care of converting the String data to the requested type."
EasyTest works on row basis (as per my knowledge).
They have not given any provision for handling List of objects.
I am using the same way. I feel it easier for primitive types but what about List of Objects..?
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
When writing Java stored procedures, I often receive values via oracle.sql.ARRAY parameters. However, how do I export values via oracle.sql.ARRAY parameters? For example:
public static void fetchFavoriteFoods(oracle.sql.ARRAY favoriteFoods) {
// What must be done here to add "pizza" and "cheese burger" to favoriteFoods?
}
Simply put, you don't.
java.sql.Array and its implementations (like oracle.sql.ARRAY) are
a logical pointer to the data in the
SQL ARRAY value rather than containing
the ARRAY value's data.
Needless to say, this means that they are read-only values.
This should be along the lines of what you are looking for:
Oracle ARRAY type usage
Basically, you can create an object of your own oracle.sql.ARRAY and use it.