Oracle8i SQLJ Developer's Guide and Reference
Release 2 (8.1.6)

A81360-01

Library

Product

Contents

Index

Prev  Chap Top Next

Serializing Java Objects through Custom Java Classes

"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.

SerializableDatum (Step by Step Example)


Note:

This application uses classes from the java.io, java.sql, oracle.sql, and oracle.jdbc.driver packages. The import statements are not shown here.  


  1. Begin with a skeleton of the class.

    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.

  1. Define client methods that perform the following:

    • Create a SerializableDatum object.

    • Populate a SerializableDatum object.

    • Retrieve data from a 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;
      }
      
      
  2. Implement a 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()); }
    
    
  3. Implement data conversion from an 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()); }
    }
    
    
  4. Implement a 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);
       }
    };
    
    

SerializableDatum in SQLJ Applications

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));

SerializableDatum as Host Variable

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) };
...

SerializableDatum in Iterator Column

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();
...

SerializableDatum (Complete Class)

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;
}




Prev

Top

Next
Oracle
Copyright © 1999 Oracle Corporation.

All Rights Reserved.

Library

Product

Contents

Index