Oracle8i SQLJ Developer's Guide and Reference
Release 8.1.5

A64684-01

Library

Product

Contents

Index

Prev  Chap Top Next

Serializing Java Objects through Custom Java Classes

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.

SerializableDatum (Step by Step Example)

  1. Begin with a skeleton of the class.


Note:

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


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 which 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 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()); }
    
    
  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