9ib JAVA
9ib JAVA
• In Oracle9i
– REF CURSORS can be returned from Java stored
procedures
– REF CURSORS can be created from Java stored
procedures using JDBC
– This is an ease-of-use and flexibility
enhancement
Note: A REF CURSOR retrieved from a Java stored procedure can be used in PL/SQL blocks or
subprograms, as well as OCI and JDBC applications.
CREATE
CREATE OR
OR REPLACE
REPLACE PACKAGE
PACKAGE emp_pack
emp_pack as
as
TYPE
TYPE ref_cur_t
ref_cur_t is
is REF
REF CURSOR;
CURSOR;
END;
END;
CREATE
CREATE procedure
procedure upd_employees
upd_employees
(ref_cur_rc
(ref_cur_rc OUT
OUT emp_pack.ref_cur_t)
emp_pack.ref_cur_t) AS
AS
LANGUAGE
LANGUAGE JAVA
JAVA NAME
NAME
'extjavaproc.proc1
'extjavaproc.proc1
(java.sql.ResultSet[])';
(java.sql.ResultSet[])';
CREATE
CREATE FUNCTION
FUNCTION del_employees
del_employees
RETURN
RETURN emp_pack.ref_cur_t
emp_pack.ref_cur_t AS
AS
LANGUAGE
LANGUAGE JAVA
JAVA NAME
NAME ''
extjavaproc.func()
extjavaproc.func() RETURNS
RETURNS
java.sql.ResultSet';
java.sql.ResultSet';
ResultSet
ResultSet rset
rset == null;
null;
ResultSet
ResultSet rr == stmt.executeQuery("SELECT
stmt.executeQuery("SELECT
CURSOR(SELECT
CURSOR(SELECT ** FROM
FROM employees
employees )) FROM
FROM
employees");
employees");
IF
IF (r.next())
(r.next())
{{
System.out.println("func3
System.out.println("func3 got
got ename
ename "" ++
r.getString(1));
r.getString(1));
rset
rset == ((OracleResultSet)r).getCursor(2)
((OracleResultSet)r).getCursor(2) ;;
}}
((OracleConnection)conn).setCreateStatement
((OracleConnection)conn).setCreateStatement As
As
RefCursor(true);
RefCursor(true);
Statement
Statement stmt
stmt == conn.createStatement();
conn.createStatement();
ResultSet
ResultSet rset
rset == stmt.executeQuery
stmt.executeQuery
("SELECT
("SELECT ** FROM
FROM employees");
employees");
...
...
Overview
Oracle9i database supports inheritance for object types, including the ability to define, store and
retrieve subtype instances within the database, and manipulating them in languages, interfaces,
utilities and tools.
Oracle9i JDBC drivers transparently recognize the object subtypes, build the type inheritance
hierarchy, determine the supertype attributes, check the attribute substitution and handle several other
tasks.
REFERENCE
Note: For more information on Object Inheritance please refer to the Objects module under
Development Platform
Substitutability in JDBC
Object type inheritance is introduced in Oracle9i object-relational database. It allows a new object
type to be created by extending another object type. The new object type is then a subtype of the
object type it extends from. The subtype automatically inherits all attributes and methods defined in
the superclass. The subtype can add attributes and methods, and overload /override methods inherited
from the supertype.
REFERENCE:
Note : For more information on Object enhancements please refer to the Objects module under
Development Platform
Person_t
Student_t
Parttimestudent_t
Type Hierarchy
An object type can be created as a subtype of an existing object type. This is based on a single
inheritance model which means that the subtype can be derived from only one parent type. A type
inherits all the attributes and methods of its direct supertype. It can add new attributes and methods
and further, override any of the inherited methods.
The above figure illustrates a subtypes Student_t created under Person_t. Further a subtype can itself
be refined by defining another subtype under it thus forming type hierarchies. In the figure above
parttimestudent_t is derived from subtype student_t.
To create a database subtype in JDBC, the most common way is to pass the "create type" statement
to the Statement::execute() API.
Note: In prior releases CustomDatum was used for object access. CustomDatum is still available for
backward compatibility
SQLData Mapping
For example the PERSON_T's SQLData class and STUDENT_T's SQLData class are as follows :
Person.java:
import java.sql.*;
public class Person implements SQLData
{
private String sql_type;
public int ssn;
public String name;
public String address;
public Person () {}
public String getSQLTypeName() throws SQLException { ret urn
sql_type; }
…
OraData Mapping
For example, the OraData class of PERSON_T and the OraData class of STUDENT_T can be
implemented as follows :
Person.java:
class Person implements OraData, OraDataFactory
{
static final Person _personFactory = new Person();
public NUMBER ssn;
public CHAR name;
public CHAR address;
public static OraDataFactory getFactory()
{
return _personFactory;
}
public Person () {}
public Person(NUMBER ssn, CHAR name, CHAR address)
{this.ssn = ssn;
this.name = name;
this.address = address;
} …
The OraData class hierarchy need not mirror the database object type hierarchy. The class Student
above could have been declared without a superclass. In this case, Student could contain fields to
hold the inherited attributes from PERSON_T as well as the attributes declared by STUDENT_T.
OraDataFactory Implementation
For example the database table is created and populated
as follows -
Note: the SQLData, OraData and OraDataFactory customized classes can be created by JDBC
application developers by means other than JPublisher.
if (s != null)
{
if (s instanceof Person)
System.out.println ("This is a Person");
else if (s instanceof Student)
System.out.println ("This is a Student");
else if (s instanceof ParttimeStudent)
System.out.pritnln ("This is a PartimeStudent");
else
System.out.println ("Unknown type");
}
}
The JDBC drivers check the connection typemap for each call to ResultSet::getObject(),
CallableStatement::getObject(), java.sql.Struct::getAttribute(), java.sql.Array::getArray() and
oracle.sql.REF::getValue().
"s" is initialized with data fields inherited from PERSON_T and STUDENT_T,
and data fields defined in PARTTIMESTUDENT_T.
REFERENCE
Note: For more examples and APIs usage, please refer to Working with Oracle Object Types,
Oracle8i JDBC Developer's Guide and Reference, Release 2 (8.1.6).
With default mapping, the logic to access the subtype data fields is
defined in the JDBC application itself.
Metadata APIs
StructDescriptor has the following methods
• String[ ] getSubtypeNames() : returns the SQL type names of the direct subtypes.
•Boolean isFinalType() : indicates whether the object type is a final type.
•String getSupertypeName() : returns the SQL type names of the direct supertype.
•int getLocalAttributeCount() : returns the number of attributes defined in the subtype.
An object type is FINAL if no subtypes can be created for this type. The default is FINAL, and a
type declaration must have NOT FINAL keyword to be "subtypable". An object type is NOT
INSTANTIABLE if it's not possible to construct instances of this type.
StructMetaData provides inheritance metadata APIs for subtype attributes.
StructDescriptor::getMetaData() returns a instance of StructMetaData of the type. It contains the
following inheritance metadata APIs
• int getLocalColumnCount() : returns the number of attributes defined in the subtype.
Same as StructDescriptor::getLocalAttributeCount().
• Boolean isInherited(int column) : indicates whether the attribute is inherited. The column
begins with 1.
Connection
Connection conn
conn == ...//create
...//create database
database connection
connection
Statement
Statement stmt
stmt == conn.createStatement();
conn.createStatement();
//
// open
open aa database
database cursor
cursor
stmt.execute("CREATE
stmt.execute("CREATE TYPE
TYPE first_level
first_level ASAS TABLE
TABLE OFOF
NUMBER");
NUMBER"); //
// create
create aa nested
nested table
table of
of number
number
stmt.execute("CREATE
stmt.execute("CREATE second_level
second_level AS AS TABLE
TABLE OFOF
first_level");
first_level"); //
// create
create aa two
two levels
levels nested
nested table
table
...
... //
// other
other operations
operations here
here
stmt.close();
stmt.close();
//
// release
release the
the resource
resource
conn.close();
conn.close();
//
// close
close the
the database
database connection
connection
//
// tab1.b
tab1.b is
is aa multi
multi level
level collection
collection column
column
ResultSet
ResultSet rset
rset == stmt.executeQuery
stmt.executeQuery ("select
("select bb
from
from tab1");
tab1");
while
while (rset.next())
(rset.next())
oracle.sql.ARRAY
oracle.sql.ARRAY multilevelCollection
multilevelCollection ==
(oracle.sql.ARRAY)
(oracle.sql.ARRAY) rset.getObject(1);
rset.getObject(1);
……
//
// obtain
obtain aa type
type descriptor
descriptor of
of "SCOTT.VARRAY3"
"SCOTT.VARRAY3"
ArrayDescriptor
ArrayDescriptor desc
desc ==
ArrayDescriptor.createDescriptor("SCOTT.VARRAY3",
ArrayDescriptor.createDescriptor("SCOTT.VARRAY3", conn);
conn);
//
// prepare
prepare the
the multi
multi level
level collection
collection elements
elements as
as aa
nested
nested Java
Java array
array
int[][][]
int[][][] elems
elems == {{{1},{1,
{{{1},{1, 2}},{{2},{2,
2}},{{2},{2, 3}},{{3},{3,
3}},{{3},{3, 4}}};
4}}};
//
// create
create the
the ARRAY
ARRAY by
by calling
calling the
the constructor
constructor
ARRAY
ARRAY array3
array3 == new
new ARRAY
ARRAY (desc,
(desc, conn,
conn, elems);
elems);
//
// some
some operations
operations
...
...
//
// close
close the
the database
database connection
connection
conn.close();
conn.close();
while (rset.next())
{
ARRAY varray3 = (ARRAY) rset.getObject (1);
Object varrayElems = varray3.getArray (1); // access array elements of "varray3"
Datum[] varray3Elems = (Datum[]) varrayElems;
while (varray1Elems.next())
System.out.println ("idx="+varray1Elems.getInt(1)+" value="+varray1Elems.getInt(2));
}
}
}
rset.close ();
stmt.close ();
conn.close ();
MetaData APIs
For example:
Connection conn = ...; // make a JDBC connection
Statement stmt = conn.createStatement ();
stmt.execute ("CREATE TYPE varray1 AS VARRAY(10) OF NUMBER(1 2,
2)");
stmt.execute ("CREATE TYPE varray2 AS VARRAY(10) OF varray1" );
stmt.execute ("CREATE TYPE varray3 AS VARRAY(10) OF varray2" );
stmt.close ();
ArrayDescriptor desc =
ArrayDescriptor.createDescriptor("VARRAY3", conn);
// expects the value of java.sql.Types.Array
System.out.println ("Element type of VARRAY3 = "+desc.getBas eType
());
// expects "SCOTT.VARRAY2"
System.out.println ("Element type of VARRAY3 = "+desc.getBas eName
());
conn.close();
TimeZone
TimeZone tz
tz == TimeZone.getDefault();
TimeZone.getDefault();
tz.setID("US_PACIFIC");
tz.setID("US_PACIFIC");
GregorianCalendar
GregorianCalendar gcal
gcal == new
new
GregorianCalendar(tz);
GregorianCalendar(tz);
Length Semantics
Byte Semantics
A string using byte semantics measures its length in bytes. Translating the string from one character set
to another can change its length. In prior Oracle databases support only byte semantics for variable
width character sets. Nchar supports codepoint semantics for fixed width character sets. An n-byte string
will always need nbytes of memory.
Codepoint Semantics
Every character set has its own idea of what a character is. Counting characters in the way the current
character set defines character is known as Codepoint Semantics. In Oracle9i every supported character
set has codepoint semantics equivalent to UCS2 semantics. Translating a string from one character set to
another may change its codepoint length. Each character set has an upper bound on the number of bytes
required to represent one of its codepoints, usually between 1 and 4.
UCS2 Semantics
A string using UCS2 semantics measures its length by effectively being translated first to UTF-16 then
measuring UCS2 codepoints. Translating the string from onecharacter set to another will not change its
length in UCS2 codepoints. Not all strings that can fit in a 10-character display can be represented with
10 UCS2 codepoints, since some characters consist of multiple codepoints. Java and Microsoft use
UCS2 semantics for strings. Thai is a language whose characters require multiple UCS2 codepoints. A
string with n UCS2 codepoints will need between n and 3n bytes of memory in UTF-8, or exactly 2n
bytes of memory in AL16UTF16.
REFERENCE
Note: For more information on SQLJ Objects please refer to the lesson on SQLJ Objects in the
Objects module