Oracle8i SQLJ Developer's Guide and Reference Release 2 (8.1.6) A81360-01 |
|
"Additional Uses for CustomDatum Implementations" includes examples of situations where you might want to define a custom Java class that maps to some oracle.sql.*
type other than the oracle.sql.STRUCT
, oracle.sql.REF
, or oracle.sql.ARRAY
type.
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 the oracle.sql.RAW
type.
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 "Custom Java Classes".
The example starts with a step-by-step approach to the development of SerializableDatum
, followed by the complete sample code.
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 oracle.sql.RAW
instance.
// 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; }