Oracle8i SQLJ Developer's Guide and Reference Release 8.1.5 A64684-01 |
|
In "Additional Uses for Custom Java Classes", there are examples of situations where you may want to define a custom Java class that maps to some oracle.sql.*
type other than oracle.sql.STRUCT
, oracle.sql.REF
, or oracle.sql.ARRAY
.
An example of such a situation is if you want to serialize and deserialize Java objects into and out of RAW
fields in the database, with a custom Java class that maps to type oracle.sql.RAW
.
This section provides an example of such an application, creating a class SerializableDatum
that implements the CustomDatum
interface and follows the general form of custom Java classes, as described in "About Custom Java Classes and the CustomDatum Interface".
The example starts with a step-by-step approach to the development of SerializableDatum
, followed by the complete sample code.
Note:
This application uses classes from the packages |
public class SerializableDatum implements CustomDatum { // <Client methods for constructing and accessing the Java object> public Datum toDatum(OracleConnection c) throws SQLException { // <Implementation of toDatum()> } public static CustomDatumFactory getFactory() { return FACTORY; } private static final CustomDatumFactory FACTORY = // <Implementation of a CustomDatumFactory for SerializableDatum> // <Construction of SerializableDatum from oracle.sql.RAW> public static final int _SQL_TYPECODE = OracleTypes.RAW; }
SerializableDatum
does not implement the CustomDatumFactory
interface, but its getFactory()
method returns a static member that implements this interface.
The _SQL_TYPECODE
is set to OracleTypes.RAW
because this is the datatype being read from and written to the database. The SQLJ translator needs this typecode information in performing online type-checking to verify compatibility between the user-defined Java type and the SQL type in the database.
SerializableDatum
object
SerializableDatum
object
SerializableDatum
object
// Client methods for constructing and accessing a SerializableDatum private Object m_data; public SerializableDatum() { m_data = null; } public void setData(Object data) { m_data = data; } public Object getData() { return m_data; }
toDatum()
method that serializes data from a SerializableDatum
object to an oracle.sql.RAW
object. The implementation of toDatum()
must return a serialized representation of the object in the m_data
field as an instance of oracle.sql.RAW
.
// Implementation of toDatum() try { ByteArrayOutputStream os = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(os); oos.writeObject(m_data); oos.close(); return new RAW(os.toByteArray()); } catch (Exception e) { throw new SQLException("SerializableDatum.toDatum: "+e.toString()); }
oracle.sql.RAW
object to a SerializableDatum
object. This step deserializes the data.
// Constructing SerializableDatum from oracle.sql.RAW private SerializableDatum(RAW raw) throws SQLException { try { InputStream rawStream = new ByteArrayInputStream(raw.getBytes()); ObjectInputStream is = new ObjectInputStream(rawStream); m_data = is.readObject(); is.close(); } catch (Exception e) { throw new SQLException("SerializableDatum.create: "+e.toString()); } }
CustomDatumFactory
. In this case, it is implemented as an anonymous class.
// Implementation of a CustomDatumFactory for SerializableDatum new CustomDatumFactory() { public CustomDatum create(Datum d, int sqlCode) throws SQLException { if (sqlCode != _SQL_TYPECODE) { throw new SQLException("SerializableDatum: invalid SQL type "+sqlCode); } return (d==null) ? null : new SerializableDatum((RAW)d); } };
Given the SerializableDatum
class created in the preceding section, this section shows how to use an instance of it in a SQLJ application, both as a host variable and as an iterator column.
Presume the following table definition:
CREATE TABLE PERSONDATA (NAME VARCHAR2(20) NOT NULL, INFO RAW(2000));
Following is an example of using a SerializableDatum
instance as a host variable.
... SerializableDatum pinfo = new SerializableDatum(); pinfo.setData ( new Object[] {"Some objects", new Integer(51), new Double(1234.27) } ); String pname = "MILLER"; #sql { INSERT INTO persondata VALUES(:pname, :pinfo) }; ...
Here is an example of using SerializableDatum
as a named iterator column.
Declaration:
#sql iterator PersonIter (SerializableDatum info, String name);
Executable code:
PersonIter pcur; #sql pcur = { SELECT * FROM persondata WHERE info IS NOT NULL }; while (pcur.next()) { System.out.println("Name:" + pcur.name() + " Info:" + pcur.info()); } pcur.close(); ...
This section shows you the entire SerializableDatum
class previously developed in step-by-step fashion.
import java.io.*; import java.sql.*; import oracle.sql.*; import oracle.jdbc.driver.*; public class SerializableDatum implements CustomDatum { // Client methods for constructing and accessing a SerializableDatum private Object m_data; public SerializableDatum() { m_data = null; } public void setData(Object data) { m_data = data; } public Object getData() { return m_data; } // Implementation of toDatum() public Datum toDatum(OracleConnection c) throws SQLException { try { ByteArrayOutputStream os = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(os); oos.writeObject(m_data); oos.close(); return new RAW(os.toByteArray()); } catch (Exception e) { throw new SQLException("SerializableDatum.toDatum: "+e.toString()); } } public static CustomDatumFactory getFactory() { return FACTORY; } // Implementation of a CustomDatumFactory for SerializableDatum private static final CustomDatumFactory FACTORY = new CustomDatumFactory() { public CustomDatum create(Datum d, int sqlCode) throws SQLException { if (sqlCode != _SQL_TYPECODE) { throw new SQLException( "SerializableDatum: invalid SQL type "+sqlCode); } return (d==null) ? null : new SerializableDatum((RAW)d); } }; // Constructing SerializableDatum from oracle.sql.RAW private SerializableDatum(RAW raw) throws SQLException { try { InputStream rawStream = new ByteArrayInputStream(raw.getBytes()); ObjectInputStream is = new ObjectInputStream(rawStream); m_data = is.readObject(); is.close(); } catch (Exception e) { throw new SQLException("SerializableDatum.create: "+e.toString()); } } public static final int _SQL_TYPECODE = OracleTypes.RAW; }