As I’ve promised in post “Learn to pass a Java Object as Oracle Procedure parameter“, I’ll show how retrieve object that have a collection of objects as attribute through of an Oracle procedure. Is highly recommended to read previous post.
For this tutorial, we’ll need create the table TBL_CLASS and add your primary key as foreign key in TBL_USER table.
--num class is PK and desc_class description create table TBL_CLASS (num_class number, desc_class varchar(100)); alter table TBL_CLASS add primary key(num_class); alter table TBL_USER add num_class number; alter table TBL_USER add constraint FK_CLASS foreign key(num_class) references tbl_class(num_class);
Now we need to include the new types:
create or replace type class_type as object (num_class number, desc_class varchar2(100), users arr_users); / create or replace type arr_class as table of class_type; /
The class_type type will be the Java Object. Notice that in your signature was included the arr_users type, that will be our collection of user_type (read previous post for more information), the arr_class type will be the class_type collection.
Now we’ll include the procedure that returns our class_type collection.
procedure pro_select_class(clas in class_type, class_return in out arr_class)is
class_ref_cur ref_cur;
--class_type array
classes arr_class := arr_class();
begin
open class_ref_cur for
select cast(
multiset(
select num_class,
desc_class,
(select cast(
multiset(
select user_name,
height,
b_date
from tbl_user
--JOIN with TBL_USER
where tbl_user.num_class = tbl_class.num_class
) as arr_users)
from dual) users
from tbl_class
--Using num_class attribute of in parameter
where num_class = clas.num_class) as arr_class
) classes
from dual;
--including the return in array
fetch class_ref_cur into classes;
--transferring arrar to variable out
class_return := classes;
end pro_select_class;
Notice that procedure receive class_type as parameter in and returns arr_class type.
Separating code charge back and set up our objects, we have:
--Mount return
select cast(
multiset(
--Will returns the objects class_type and your attributes
select num_class,
desc_class,
--Populate user_type collection
(select cast(
multiset(
select user_name,
height,
b_date
from tbl_user
where tbl_user.num_class = tbl_class.num_class
) as arr_users)
from dual) users
from tbl_class
where num_class = clas.num_class) as arr_class
) classes
from dual;
Oracle objects done, now the Java code!
We’ll create the object that will be interpreted by the Oracle. Called TypeClass:
public class TypeClass implements SQLData{
public static final String ORACLE_OBJECT_NAME = "CLASS_TYPE"; //Type name in Oracle
public static final String ORACLE_CLASS_ARRAY_NAME = "ARR_CLASS"; //Array name in Oracle
//Attibutes of TBL_CLASS table
private Long number;
private String desc;
private Array users; //This will be user_type collection (or TypeUser in Java)
public String getSQLTypeName() throws SQLException {
return ORACLE_OBJECT_NAME;
}
public void readSQL(SQLInput stream, String typeName) throws SQLException {
setNumber(stream.readLong());
setDesc(stream.readString());
setUsers(stream.readArray());//Used by JDBC driver to read the collection
}
public void writeSQL(SQLOutput stream) throws SQLException {
stream.writeLong(getNumber());
stream.writeString(getDesc());
stream.writeArray(getUsers());//Used by JDBC driver to write the collection
}
//Getters and setters omitted
}
We need to map types interpreted in request, this way:
Map> typeMaps = connection.getTypeMap(); typeMaps.put(TypeUser.ORACLE_OBJECT_NAME, TypeUser.class); typeMaps.put(TypeClass.ORACLE_OBJECT_NAME, TypeClass.class);
We need to map the arrays too:
typeMaps.put(TypeClass.ORACLE_CLASS_ARRAY_NAME, TypeClass[].class);//returned by procedure typeMaps.put(TypeUser.ORACLE_USER_ARRAY_NAME, TypeUser[].class);//returned by class_type collection
For request, we do:
cs = conn.prepareCall("{call PAC_BEAN.PRO_SELECT_CLASS(?,?)}");
//registering out type, that will be a TypeClass array
cs.registerOutParameter("class_return", OracleTypes.ARRAY, TypeClass.ORACLE_CLASS_ARRAY_NAME);
//passing parameter object
cs.setObject("clas", classQry);
cs.execute();
//retrieving and looping the TypeClass array
Object[] array = (Object[])cs.getArray("class_return").getArray();
for(Object obj : array){
TypeClass objClass = ((TypeClass)obj);
System.out.println("Description: "+objClass.getDesc());
//Here we obtains user_type(TypeUser) array returned by query.
Object[] userArray = (Object[])objClass.getUsers().getArray();
for(Object user : userArray){
System.out.println("\tName: " + ((TypeUser)user).getName());
System.out.println("\tHeight: " + ((TypeUser)user).getHeight());
System.out.println("\tBirth: " + sdf.format(((TypeUser)user).getBirth())+ "\r\n");
}
}
In the end you’ll have a java.sql.Array of TypeUser in getUsers() attribute of TypeClass.
Here I fulfilled my promise. Download the source code of this sample (with previous post sample too) here.
Until next time!
1 Trackback or Pingback for this entry
September 21st, 2009 on 19:55
[...] So we can pass and retrieve simple Java objects of a Oracle procedure or function. The next step, Retrieving objects collection from Oracle procedure. [...]