Oracle8i SQLJ Developer's Guide and Reference Release 3 (8.1.7) Part Number A83723-01 |
Library | Service | Contents | Index

## JPublisher and the Creation of Custom Java Classes

Oracle offers flexibility in how users can customize the mapping of Oracle object types, reference types, and collection types to Java classes in a strongly typed paradigm. Developers have the following choices in creating these custom Java classes:

- using Oracle JPublisher to automatically generate custom Java classes and using those classes directly without modification

- using JPublisher to automatically generate custom Java classes and subclassing them to create custom Java classes with added functionality

- manually coding custom Java classes without using JPublisher, provided that the classes meet the requirements stated in "Custom Java Class Requirements"

Although you have the option of manually coding your custom Java classes, using JPublisher is advisable. If you need special functionality, you can subclass a class that JPublisher generates.

JPublisher can implement either the Oracle `oracle.sql.CustomDatum` interface or the standard `java.sql.SQLData` interface when it generates a custom object class. If you choose the `CustomDatum` implementation, then JPublisher will also generate a custom reference class.

The `SQLData` interface is not intended for custom reference or custom collection classes. If you want your code to be portable, you have no choice but to use standard, weakly typed `java.sql.Ref` objects to map to references, and `java.sql.Array` objects to map to collections.

This manual provides only a minimal level of information and detail regarding the JPublisher utility. See the Oracle8i JPublisher User's Guide for more information.

### What JPublisher Produces

When you use JPublisher to generate custom Java classes, you can use either a `CustomDatum` implementation (for custom object classes, custom reference classes, or custom collection classes) or a `SQLData` implementation (for custom object classes only). A `CustomDatum` implementation will also implement the `CustomDatumFactory` interface, for creating instances of the custom Java class.

This is controlled by how you set the JPublisher `-usertypes` option. A setting of `oracle` specifies a `CustomDatum` implementation; a setting of `jdbc` specifies a `SQLData` implementation.

#### CustomDatum Implementation

When you run JPublisher for a user-defined object type and choose the `CustomDatum` (and `CustomDatumFactory`) implementation for your custom object class, JPublisher automatically creates the following:

- a custom object class to act as a type definition to correspond to your Oracle object type

  This class includes getter and setter methods for each attribute. The method names are of the form `getFoo()` and `setFoo()` for attribute `foo`.

  In addition, JPublisher by default will generate wrapper methods in your class that invoke the associated Oracle object methods executing in the server. This can be disabled, however, by setting `-methods=false`. This option is described later in this section.

- a related custom reference class for object references to your Oracle object type

  This class includes a `getValue()` method that returns an instance of your custom object class, and a `setValue()` method that updates an object value in the database, taking as input an instance of the custom object class.

- custom classes for any object or collection attributes of the top-level object

  This is necessary so that attributes can be materialized in Java whenever an instance of the top-level class is materialized.

When you run JPublisher for a user-defined collection type, choosing the `CustomDatum` implementation, JPublisher automatically creates the following:

- a custom collection class to act as a type definition to correspond to your Oracle collection type

  This class includes overloaded `getArray()` and `setArray()` methods to retrieve or update a collection as a whole, a `getElement()` method and `setElement()` method to retrieve or update individual elements of a collection, and additional utility methods.

- a custom object class for the elements, if the elements of the collection are objects

  This is necessary so that object elements can be materialized in Java whenever an instance of the collection is materialized.

JPublisher-generated custom Java classes in any of these categories implement the `CustomDatum` interface, the `CustomDatumFactory` interface, and the `getFactory()` method.

Note: If you specify the `CustomDatum` implementation, the generated classes will use Oracle-specific features and therefore will not be portable.

#### SQLData Implementation

As with the `CustomDatum` implementation, when you run JPublisher for a user-defined object type and choose the `SQLData` implementation for your custom object class, JPublisher will produce a custom object class to act as a type definition to correspond to your Oracle object type. This class will include the following:

- getter and setter methods for each attribute

- implementations of the standard `SQLData` interface `readSQL()` and `writeSQL()` methods

- wrapper methods that invoke the Oracle object methods executing in the server (unless you specify `-methods=false` when you run JPublisher)

Because the `SQLData` interface is intended only for objects, however, and not for references or collections, JPublisher will not generate a custom reference class for references to the Oracle object type. You will have to use standard, weakly typed `java.sql.Ref` instances, or perhaps `oracle.sql.REF` instances if you do not require portability. Note that `REF` instances, like custom reference class instances, have Oracle extension methods `getValue()` and `setValue()` to read or write instances of the referenced object. Standard `Ref` instances do not have this functionality.

Similarly, because you cannot use a `SQLData` implementation for a custom collection class, you must use standard, weakly typed `java.sql.Array` instances, or perhaps `oracle.sql.ARRAY` instances if you do not require portability. `Array` and `ARRAY` instances, like custom collection class instances, have `getArray()` functionality to read the collection as a whole or in part, but do not have the element-level access and writability offered by the custom collection class `getElement()` and `setElement()` methods.

Note: The `SQLData` interface is defined in the JDBC 2.0 specification to be portable. However, if you want the `SQLData` implementation produced by JPublisher to be portable, you must avoid using any Oracle-specific features and Oracle type mapping (which uses the Oracle-specific `oracle.sql.*` classes).

### Generating Custom Java Classes

This section discusses key JPublisher command-line functionality for specifying the user-defined types that you want to map to Java and for specifying object class names, collection class names, attribute type mappings, and wrapper methods. These key points can be summarized as follows:

- Specify user-defined types to map to Java. You can specify the custom object and custom collection class names for JPublisher to use, or you can accept the default names (use the JPublisher `-sql`, `-user`, and `-case` options).

- Specify the implementation to use (`CustomDatum` or `SQLData`; use the JPublisher `-usertypes` option).

- Optionally specify attribute type mappings (use the JPublisher `-XXXtypes` options: `-numbertypes`, `-builtintypes`, and `-lobtypes`).

- Choose whether or not JPublisher will create wrapper methods, in particular for Oracle object methods (use the JPublisher `-methods` flag, which is enabled by default).

  Note: Throughout this section, any discussion of custom reference classes or custom collection classes refers only to `CustomDatum` implementations.

#### Specify User-Defined Types to Map to Java

In using JPublisher to create custom Java classes, use the `-sql` option to specify the user-defined SQL types that you want to map to Java. You can either specify the custom object class names and custom collection class names, or you can accept the defaults.

The default names of your top-level custom classes--the classes that will correspond to the user-defined type names you specify to the `-sql` option--are identical to the user-defined type names as you enter them on the JPublisher command line. Because SQL names in the database are case-insensitive, you can capitalize them to ensure that your class names are capitalized per Java convention. For example, if you want to generate a custom class for `employee` objects, you can run JPublisher as follows:

    % jpub -sql=Employee ...

The default names of lower-level classes, such as for `home_address` objects that are attributes of `employee` objects, are determined by the JPublisher `-case` option. If you do not set the `-case` option, it is set to `mixed`. This means that the default for the custom class name is to capitalize the initial character of the corresponding user-defined type name and the initial character of every word unit thereafter. JPublisher interprets underscores (_), dollar signs ($), and any characters that are illegal in Java identifiers as word-unit separators; these characters are discarded in the process.

For example, for Oracle object type `home_address`, JPublisher would create class `HomeAddress` in a `HomeAddress.java` source file.

Notes: Remember that Java class names are case-sensitive, although Oracle object and collection names (and SQL names in general) are not. For backwards compatibility to previous versions of JPublisher, the `-types` option is still accepted as an alternative to `-sql`.

On the JPublisher command line, use the following syntax for the `-sql` option (you can specify multiple actions in a single option setting).

    -sql=udt1<:mapclass1><,udt2<:mapclass2>>,...,<udtN<:mapclassN>> ...

And use the `-user` option to specify the database schema. Following is an example:

    % jpub -sql=Myobj,mycoll:MyCollClass -user=scott/tiger

(There can be no space before or after the comma.)

For the Oracle object `MYOBJ`, this command will name it as you typed it, creating source `Myobj.java` to define a `Myobj` class. For the Oracle collection `MYCOLL`, this command will create source `MyCollClass.java` to define a `MyCollClass` class.

You can optionally specify schema names in the `-sql` option--for example, the `scott` schema:

    % jpub -sql=scott.Myobj,scott.mycoll:MyCollClass -user=scott/tiger

You cannot specify custom reference class names; JPublisher automatically derives them by adding `Ref` to custom object class names (relevant to `CustomDatum` implementations only). For example, if JPublisher produces Java source `Myobj.java` to define custom object class `Myobj`, then it will also produce Java source `MyobjRef.java` to define a `MyobjRef` custom reference class.

Note: When specifying the schema, such as `scott` in the above example, this is not incorporated into the custom Java class name.

To create custom Java classes for the object and collection types defined in "User-Defined Types in the Database", you can run JPublisher as follows:

    %jpub -user=scott/tiger -sql=Address,Person,Phone_array,Participant_t,
    Module_t,Moduletbl_t

Or, to explicitly specify the custom object class and custom collection class names:

    %jpub -user=scott/tiger -sql=Address,Person,phone_array:PhoneArray,
    participant_t:ParticipantT,module_t:ModuleT,moduletbl_t:ModuletblT

(Each of the preceding two examples is a single wrap-around command line.)

The second example will produce Java source files `Address.java`, `AddressRef.java`, `Person.java`, `PersonRef.java`, `PhoneArray.java`, `ParticipantT.java`, `ParticipantTRef.java`, `ModuleT.java`, `ModuleTRef.java`, and `ModuletblT.java`. Examples of some of these source files are provided in "JPublisher Custom Java Class Examples".

So that it knows how to populate the custom Java classes, JPublisher connects to the specified schema (here, `scott/tiger`) to determine attributes of your specified object types or elements of your specified collection types.

If you want to change how JPublisher uses character case in default names for the methods and attributes that it generates, including lower-level custom Java class names for attributes that are objects or collections, you can accomplish this using the `-case` option. There are four possible settings:

- `-case=mixed` (default)--The following will be uppercase: the first character of every word unit of a class name, every word unit of an attribute name, and every word unit after the first word unit of a method name. All other characters are in lowercase. JPublisher interprets underscores (_), dollar signs ($), and any characters that are illegal in Java identifiers as word-unit separators; these characters are discarded in the process.

- `-case=same`--Character case is unchanged from its representation in the database. Underscores and dollar signs are retained; illegal characters are discarded.

- `-case=upper`--Lowercase letters are converted to uppercase. Underscores and dollar signs are retained; illegal characters are discarded.

- `-case=lower`--Uppercase letters are converted to lowercase. Underscores and dollar signs are retained; illegal characters are discarded.

  Note: If you run JPublisher without specifying the user-defined types to map to Java, it will process all user-defined types in the schema. Generated class names, for both your top-level custom classes and any lower-level classes for object attributes or collection elements, will be based on the setting of the `-case` option.

#### Specify Type Mappings

JPublisher offers several choices for how to map user-defined types and their attribute and element types between SQL and Java. The rest of this section lists categories of SQL types and the mapping options available for each category.

(See "Supported Types for Host Expressions" for general information about how Oracle datatypes map to Java types.)

For more information about JPublisher features or options, see the Oracle8i JPublisher User's Guide.

##### Categories of SQL Types

JPublisher categorizes SQL types into the following groups, with corresponding JPublisher options as noted:

- user-defined types (UDT)--Oracle objects, references, and collections

  Use the JPublisher `-usertypes` option to specify the type-mapping implementation for UDTs--either a standard `SQLData` implementation or an Oracle-specific `CustomDatum` implementation.

- numeric types--anything stored in the database as SQL type `NUMBER`

  Use the JPublisher `-numbertypes` option to specify type-mapping for numeric types.

- LOB types--SQL types `BLOB` and `CLOB`

  Use the JPublisher `-lobtypes` option to specify type-mapping for LOB types.

- built-in types--anything stored in the database as a SQL type not covered by the preceding categories, for example: `CHAR`, `VARCHAR2`, `LONG`, and `RAW`

  Use the JPublisher `-builtintypes` option to specify type-mapping for built-in types.

##### Type-Mapping Modes

JPublisher defines the following type-mapping modes, two of which apply to numeric types only:

- JDBC mapping (setting `jdbc`)--Uses standard default mappings between SQL types and Java native types. For a custom object class, this specifies a `SQLData` implementation.

- Oracle mapping (setting `oracle`)--Uses corresponding `oracle.sql` types to map to SQL types. For a custom object, reference, or collection class, this specifies a `CustomDatum` implementation.

- object-JDBC mapping (for numeric types only) (setting `objectjdbc`)--This is an extension of JDBC mapping. Where relevant, object-JDBC mapping uses numeric object types from the standard `java.lang` package (such as `java.lang.Integer`, `Float`, and `Double`) instead of primitive Java types (such as `int`, `float`, and `double`). The `java.lang` types are nullable; the primitive types are not.

- `BigDecimal` mapping (for numeric types only) (setting `bigdecimal`)--Uses `java.math.BigDecimal` to map to all numeric attributes; appropriate if you are dealing with large numbers but do not want to map to the `oracle.sql.NUMBER` type.

  Note: Using `BigDecimal` mapping can significantly degrade performance.

##### Mapping the SQL Object Type to Java

Use the JPublisher `-usertypes` option to determine how JPublisher will implement the custom Java class that corresponds to a SQL object type:

- A setting of `-usertypes=oracle` (the default setting) instructs JPublisher to create a `CustomDatum` implementation for the custom object or collection class.

  For a custom object class, this will also result in JPublisher producing a `CustomDatum` implementation for the corresponding custom reference class.

- A setting of `-usertypes=jdbc` instructs JPublisher to create a `SQLData` implementation for the custom object class. No custom reference class can be created--you must use `java.sql.Ref` or `oracle.sql.REF` for the reference type.

  This setting is invalid for implementing a custom collection class. (The `SQLData` interface is intended for mapping SQL object types only.)

The next section discusses type mapping options that you can use for object attributes and collection elements.

##### Mapping Attribute or Element Types to Java

If you do not specify mappings for the attribute types of a SQL object type or the element types of a SQL collection type, then JPublisher uses the following defaults:

- For numeric types, the default mapping is object-JDBC.

- For LOB types, the default mapping is Oracle.

- For built-in type types, the default mapping is JDBC.

If you want alternate mappings, use the `-numbertypes`, `-lobtypes`, and `-builtintypes` options as necessary, depending on the attribute types you have and the mappings you desire.

If an attribute type is itself a SQL object type, it will be mapped according to the `-usertypes` setting.

Important: Be especially aware that if you specify a `SQLData` implementation for the custom object class and want the code to be portable, you must be sure to use portable mappings for the attribute types. The defaults for numeric types and built-in types are portable, but for LOB types you must specify `-lobtypes=jdbc`.

##### Summary of SQL Type Categories and Mapping Settings

Table 6-1 summarizes JPublisher categories for SQL types, the mapping settings relevant for each category, and the default settings.

##### Table 6-1 JPublisher SQL Type Categories, Supported Settings, and Defaults

SQL Type Category | JPublisher Mapping Option | Mapping Settings | Default
--- | --- | --- | ---
UDT types | -usertypes | oracle, jdbc | oracle
numeric types | -numbertypes | oracle, jdbc, objectjdbc, bigdecimal | objectjdbc
LOB types | -lobtypes | oracle, jdbc | oracle
built-in types | -builtintypes | oracle, jdbc | jdbc

Note: The JPublisher `-mapping` option used in previous releases will be deprecated but is currently still supported. For information about how JPublisher converts `-mapping` option settings to settings for the new mapping options, see the Oracle8i JPublisher User's Guide

.

#### Generate Wrapper Methods

In creating custom object classes to map Oracle objects to Java, the `-methods` option instructs JPublisher whether to include Java wrappers for Oracle object methods (member functions). The default `-methods=true` setting generates wrappers.

Wrapper methods generated by JPublisher are always instance methods, even when the original object methods are static. See "Custom Java Class Support for Object Methods" for more information.

The following example shows how to set the`-methods` option:

    % jpub -sql=Myobj,mycoll:MyCollClass -user=scott/tiger -methods=true

This will use default naming--the Java method names will be derived in the same fashion as custom Java class names (as described in "Specify User-Defined Types to Map to Java"), except that the initial character will be lowercase. For example, by default an object method name of `CALC_SAL` results in a Java wrapper method of `calcSal()`.

Alternatively, you can specify desired Java method names, but this requires use of a JPublisher input file and is discussed in "Creating Custom Java Classes and Specifying Member Names".

Note: The `-methods` option has additional uses as well, such as for generating wrapper classes for packages, or wrapper methods for package methods. This is beyond the scope of this manual--see the Oracle8i JPublisher User's Guide

for information.

##### Regarding Overloaded Methods

If you run JPublisher for an Oracle object that has an overloaded method where multiple signatures have the same corresponding Java signature, then JPublisher will generate a uniquely named method for each signature. It accomplishes this by appending `_n` to function names, where `n` is a number. This is to ensure that no two methods in the generated custom Java class have the same name and signature. Consider, for example, the SQL functions defined in creating a `MY_TYPE` object type:

    CREATE OR REPLACE TYPE my_type AS OBJECT
    (
       ...

       MEMBER FUNCTION myfunc(x INTEGER)
          RETURN my_return IS
          BEGIN
             ...
          END;

       MEMBER FUNCTION myfunc(y SMALLINT)
          RETURN my_return IS
          BEGIN
             ...
          END;
       ...
    );

Without precaution, both definitions of `myfunc` result in the following name and signature in Java:

    myfunc(Integer)

(Because both `INTEGER` and `SMALLINT` in SQL map to the Java `Integer` type.)

Instead, JPublisher might call one `myfunc_1` and the other `myfunc_2`. (The `_n` is unique for each. In simple cases it will likely be `_1`, `_2`, and so on, but it might sometimes be arbitrary, other than being unique for each.)

Note: How JPublisher handles overloaded wrapper methods applies to SQL functions created within an object or within a package, but not to top-level functions--overloading is not allowed at the top level.

#### Generate Custom Java Classes and Map Alternate Classes

You can use JPublisher to generate a custom Java class but instruct it to map the object type (or collection type) to an alternative class instead of to the generated class.

A typical scenario is to treat JPublisher-generated classes as superclasses, subclass them to add functionality, and map the object types to the subclasses. For example, presume you have an Oracle object type `ADDRESS` and want to produce a custom Java class for it that has functionality beyond what is produced by JPublisher. You can use JPublisher to generate a custom Java class `JAddress` for the purpose of subclassing it to produce a class `MyAddress`. Under this scenario you will add any special functionality to `MyAddress` and will want JPublisher to map `ADDRESS` objects to that class, not to the `JAddress` class. You will also want JPublisher to produce a reference class for `MyAddress`, not `JAddress`.

JPublisher has functionality to streamline the process of mapping to alternative classes. Use the following syntax in your `-sql` option setting:

    -sql=object_type:generated_class:map_class

For the above example, use this setting:

    -sql=ADDRESS:JAddress:MyAddress

This generates class `JAddress` in source file `JAddress.java`, but does the following:

- Maps the object type `ADDRESS` to the `MyAddress` class, not to the `JAddress` class. Therefore, if you retrieve an object from the database that has an `ADDRESS` attribute, then this attribute will be created as an instance of `MyAddress` in Java. Or, if you retrieve an `ADDRESS` object directly, you will retrieve it into a `MyAddress` instance.

- Creates a `MyAddressRef` class in `MyAddressRef.java`, instead of creating a `JAddressRef` class.

You must manually define a `MyAddress` class in a `MyAddress.java` source file. This class implements your required functionality by subclassing `JAddress`.

For further discussion about subclassing JPublisher-generated classes or using them as fields (continuing the preceding example), see "Extending Classes Generated by JPublisher".

### JPublisher Input Files and Properties Files

JPublisher supports the use of special input files and standard properties files to specify type mappings and additional option settings.

#### Using JPublisher Input Files

You can use the JPublisher `-input` command-line option to specify an input file for JPublisher to use for additional type mappings.

`"SQL`" in an input file is equivalent to "`-sql`" on the command line, and "`AS`" or "`GENERATE...AS`" syntax is equivalent to command-line colon syntax. Use the following syntax, specifying just one mapping per SQL command:

    SQL udt1 <GENERATE GeneratedClass1> <AS MapClass1>
    SQL udt2 <GENERATE GeneratedClass2> <AS MapClass2>
    ...

This generates `GeneratedClass1` and `GeneratedClass2`, but maps `udt1` to `MapClass1` and `udt2` to `MapClass2`.

##### Input File Example

In the following example, JPublisher will pick up the `-user` option from the command line and go to input file `myinput.in` for type mappings.

Command line:

    % jpub -input=myinput.in -user=scott/tiger

Contents of input file `myinput.in`:

    SQL Myobj
    SQL mycoll AS MyCollClass
    SQL employee GENERATE Employee AS MyEmployee

This accomplishes the following:

- User-defined type `MYOBJ` gets the custom object class name `Myobj` because that's how you typed it--JPublisher creates source `Myobj.java` (and `MyobjRef.java`).

- User-defined type `MYCOLL` is mapped to `MyCollClass`. JPublisher creates a `MyCollClass.java` source file.

- User-defined type `EMPLOYEE` is mapped to the `MyEmployee` class. JPublisher creates source `Employee.java` and `MyEmployeeRef.java`. If you retrieve an object from the database that has an `EMPLOYEE` attribute, this attribute would be created as an instance of `MyEmployee` in Java. Or if you retrieve an `EMPLOYEE` object directly, presumably you will retrieve it into a `MyEmployee` instance. You must manually create source file `MyEmployee.java` to define class `MyEmployee`, which would subclass the `Employee` class.

#### Using JPublisher Properties Files

You can use the JPublisher `-props` command-line option to specify a properties file for JPublisher to use for additional type mappings and other option settings.

In a properties file, "`jpub.`" (including the period) is equivalent to the command-line "`-`" (single-dash), and other syntax remains the same. Specify only one option per line.

For type mappings, for example, "`jpub.sql`" is equivalent to "`-sql`". As on the command line, but unlike in an input file, you can specify multiple mappings in a single `jpub.sql` setting.

##### Properties File Example

In the following example, JPublisher will pick up the `-user` option from the command line and go to properties file `jpub.properties` for type mappings and the attribute-mapping option.

Command line:

    % jpub -props=jpub.properties -user=scott/tiger

Contents of properties file `jpub.properties`:

    jpub.sql=Myobj,mycoll:MyCollClass,employee:Employee:MyEmployee
    jpub.usertypes=oracle

This produces the same results as the input-file example above, explicitly specifying the `oracle` mapping setting.

Note: Unlike SQLJ, JPublisher has no default properties file. To use a properties file, you must use the `-props` option.

### Creating Custom Java Classes and Specifying Member Names

In generating custom Java classes you can specify the names of any attributes or methods of the custom class. This cannot be specified on the JPublisher command line, however--only in a JPublisher input file using `TRANSLATE` syntax, as follows:

    SQL udt <GENERATE GeneratedClass> <AS MapClass> <TRANSLATE membername1 AS
    Javaname1> <, membername2 AS Javaname2> ...

(This is a single wrap-around command line.)

`TRANSLATE` pairs (`membernameN` `AS` `JavanameN`) are separated by commas.

For example, presume the Oracle object type `EMPLOYEE` has an `ADDRESS` attribute that you want to call `HomeAddress`, and a `GIVE_RAISE` method that you want to call `giveRaise()`. Also presume that you want to generate an `Employee` class but map `EMPLOYEE` objects to a `MyEmployee` class that you will create (this is not related to specifying member names, but provides a full example of input file syntax).

    SQL employee GENERATE Employee AS MyEmployee TRANSLATE address AS HomeAddress,
    GIVE_RAISE AS giveRaise

(This is a single wrap-around command line.)

Notes: When you specify member names, any members you do not specify will be given the default naming. The reason to capitalize the specified attribute--`HomeAddress` instead of `homeAddress`--is that it will be used exactly as specified to name the accessor methods; `getHomeAddress()`, for example, follows naming conventions; `gethomeAddress()` does not.

### JPublisher Implementation of Wrapper Methods

This section describes how JPublisher generates wrapper methods and how wrapper method calls are processed at runtime.

#### Generation of Wrapper Methods

The following points describe how JPublisher generates wrapper methods:

- JPublisher-generated wrapper methods are implemented in SQLJ; therefore, whenever `-methods=true`, the custom object class will be defined in a `.sqlj` file, instead of in a `.java` file. Run SQLJ to translate the `.sqlj` file.

- All wrapper methods generated by JPublisher are implemented as instance methods. This is because a database connection is required for you to invoke the corresponding server method. Each instance of a JPublisher-generated custom Java class has a connection associated with it.

#### Runtime Execution of Wrapper Method Calls

The following points describe what JPublisher-generated Java wrapper methods execute at runtime. In this discussion, "Java wrapper method" refers to a method in the custom Java object, while "wrapped SQL method" refers to the SQL object's method that is wrapped by the Java wrapper method.

- The custom Java object is converted to a SQL object and passed to the database, where the wrapped SQL method is invoked. After this method invocation, the new value of the SQL object is returned to Java in a new custom Java object, either as a function return from the wrapped SQL method (if the SQL method is a stored procedure), or, if there already is a function return, as an array element in an additional output parameter (this is the case if the SQL method is a stored function).

- Any output or input-output parameter is passed as the element of a one-element array. (This is to work around logistical issues with output and input-output parameters, as discussed in "Custom Java Class Support for Object Methods".) If the parameter is input-output, then the wrapper method takes the array element as input; after processing, the wrapper assigns the output to the array element.

### JPublisher Custom Java Class Examples

This section provides examples of JPublisher-generated `CustomDatum` implementations for the following user-defined types (created in "User-Defined Types in the Database"):

- a custom object class (`Address`, corresponding to the Oracle object type `ADDRESS`) and related custom reference class (`AddressRef`)

- a custom collection class (`ModuletblT`, corresponding to the Oracle collection type `MODULETBL_T`)

  Note: For examples of JPublisher-generated `SQLData` implementations, as well as further examples of JPublisher-generated `CustomDatum` implementations, see the Oracle8i JPublisher User's Guide.

#### Custom Object Class--Address.java

Following is an example of the source code that JPublisher generates for a custom object class. Implementation details have been omitted.

In this example, unlike in "Creating Object Types", assume the Oracle object `ADDRESS` has only the `street` and `zip_code` attributes.

    package bar;

    import java.sql.SQLException;
    import oracle.jdbc.driver.OracleConnection;
    import oracle.jdbc.driver.OracleTypes;
    import oracle.sql.CustomDatum;
    import oracle.sql.CustomDatumFactory;
    import oracle.sql.Datum;
    import oracle.sql.STRUCT;
    import oracle.jpub.MutableStruct;

    public class Address implements CustomDatum, CustomDatumFactory
    {
      public static final String _SQL_NAME = "SCOTT.ADDRESS";
      public static final int _SQL_TYPECODE = OracleTypes.STRUCT;

      public static CustomDatumFactory getFactory()
      { ... }

      /* constructor */
      public Address()
      { ... }

      /* CustomDatum interface */
      public Datum toDatum(OracleConnection c) throws SQLException
      { ... }

      /* CustomDatumFactory interface */
      public CustomDatum create(Datum d, int sqlType) throws SQLException
      { ... }

      /* accessor methods */
      public String getStreet() throws SQLException
      { ... }

      public void setStreet(String street) throws SQLException
      { ... }

      public String getZipCode() throws SQLException
      { ... }

      public void setZipCode(String zip_code) throws SQLException
      { ... }

    }

#### Custom Reference Class--AddressRef.java

Following is an example of the source code that JPublisher generates for a custom reference class to be used for references to `ADDRESS` objects. Implementation details have been omitted.

    package bar;

    import java.sql.SQLException;
    import oracle.jdbc.driver.OracleConnection;
    import oracle.jdbc.driver.OracleTypes;
    import oracle.sql.CustomDatum;
    import oracle.sql.CustomDatumFactory;
    import oracle.sql.Datum;
    import oracle.sql.REF;
    import oracle.sql.STRUCT;

    public class AddressRef implements CustomDatum, CustomDatumFactory
    {
      public static final String _SQL_BASETYPE = "SCOTT.ADDRESS";
      public static final int _SQL_TYPECODE = OracleTypes.REF;

      public static CustomDatumFactory getFactory()
      { ... }

      /* constructor */
      public AddressRef()
      { ... }

      /* CustomDatum interface */
      public Datum toDatum(OracleConnection c) throws SQLException
      { ... }

      /* CustomDatumFactory interface */
      public CustomDatum create(Datum d, int sqlType) throws SQLException
      { ... }

      public Address getValue() throws SQLException
      { ... }

      public void setValue(Address c) throws SQLException
      { ... }
    }

#### Custom Collection Class--ModuletblT.java

Following is an example of the source code that JPublisher generates for a custom collection class. Implementation details have been omitted.

    import java.sql.SQLException;
    import oracle.jdbc.driver.OracleConnection;
    import oracle.jdbc.driver.OracleTypes;
    import oracle.sql.CustomDatum;
    import oracle.sql.CustomDatumFactory;
    import oracle.sql.Datum;
    import oracle.sql.ARRAY;
    import oracle.sql.ArrayDescriptor;
    import oracle.jpub.runtime.MutableArray;

    public class ModuletblT implements CustomDatum, CustomDatumFactory
    {
      public static final String _SQL_NAME = "SCOTT.MODULETBL_T";
      public static final int _SQL_TYPECODE = OracleTypes.ARRAY;

      public static CustomDatumFactory getFactory()
      { ... }

      /* constructors */
      public ModuletblT()
      { ... }

      public ModuletblT(ModuleT[] a)
      { ... }

      /* CustomDatum interface */
      public Datum toDatum(OracleConnection c) throws SQLException
      { ... }

      /* CustomDatumFactory interface */
      public CustomDatum create(Datum d, int sqlType) throws SQLException
      { ... }

      public String getBaseTypeName() throws SQLException
      { ... }

      public int getBaseType() throws SQLException
      { ... }

      public ArrayDescriptor getDescriptor() throws SQLException
      { ... }

      /* array accessor methods */
      public ModuleT[] getArray() throws SQLException
      { ... }

      public void setArray(ModuleT[] a) throws SQLException
      { ... }

      public ModuleT[] getArray(long index, int count) throws SQLException
      { ... }

      public void setArray(ModuleT[] a, long index) throws SQLException
      { ... }

      public ModuleT getObjectElement(long index) throws SQLException
      { ... }

      public void setElement(ModuleT a, long index) throws SQLException
      { ... }
    }

### Extending Classes Generated by JPublisher

You might want to enhance the functionality of a custom Java class generated by JPublisher by adding methods and transient fields. You can accomplish this by subclassing the JPublisher-generated class.

For example, suppose you want JPublisher to generate the class `JAddress` from the SQL object type `ADDRESS`. You also want to write a class `MyAddress` to represent `ADDRESS` objects and implement special functionality. The `MyAddress` class must extend `JAddress`.

Another way to enhance the functionality of a JPublisher-generated class is to simply add methods to it. However, adding methods to the generated class is not recommended if you anticipate running JPublisher at some future time to regenerate the class. If you run JPublisher to regenerate a class that you have modified in this way, you would have to save a copy and then manually merge your changes back in.

#### JPublisher Functionality for Extending Generated Classes

As discussed in "Generate Custom Java Classes and Map Alternate Classes", the JPublisher syntax to generate `JAddress` but map to `MyAddress` is as follows:

    -sql=ADDRESS:JAddress:MyAddress

or, in an input file:

    SQL ADDRESS GENERATE JAddress AS MyAddress

As a result of this, JPublisher will generate the `REF` class `MyAddressRef` (in `MyAddressRef.java`) rather than `JAddressRef`.

In addition, JPublisher alters the code it generates to implement the following functionality:

- The `MyAddress` class, instead of the `JAddress` class, is used to represent attributes whose database type is `ADDRESS`.

- The `MyAddress` class, instead of the `JAddress` class, is used to represent method arguments and function results whose type is `ADDRESS`.

- The `MyAddress` factory, instead of the `JAddress` factory, is used to construct Java objects whose database type is `ADDRESS`.

You would presumably use `MyAddress` similarly in any additional code that you write.

At runtime, the Oracle JDBC driver will map any occurrences of `ADDRESS` data in the database to `MyAddress` instances, instead of to `JAddress` instances.

#### Requirements of Extended Classes

The class that you create (for example, `MyAddress.java`) must have a no-argument constructor. The easiest way to construct a properly initialized object is to invoke the constructor of the superclass, either explicitly or implicitly.

As a result of subclassing the JPublisher-generated class, the subclass will inherit definitions of the `_SQL_NAME` field, which it requires, and the `_SQL_TYPECODE` field.

In addition, one of the following will be true.

- If the JPublisher-generated class implements the `CustomDatum` and `CustomDatumFactory` interfaces, then the subclass will inherit this implementation and the necessary `toDatum()`, and `create()` functionality of the generated class. You must implement a `getFactory()` method that returns an instance of your map class (such as a `MyAddress` object).

or:

- If the JPublisher-generated class implements the `SQLData` interface, then the subclass will inherit this implementation and the necessary `readSQL()` and `writeSQL()` functionality of the generated class.

#### JPublisher-Generated Custom Object Class--JAddress.java

Continuing the example in the preceding sections, here is sample code for the JPublisher-generated class (`JAddress`), implementing `CustomDatum` and `CustomDatumFactory`. Implementation details have been omitted.

    import java.sql.SQLException;
    import oracle.jdbc.driver.OracleConnection;
    import oracle.jdbc.driver.OracleTypes;
    import oracle.sql.CustomDatum;
    import oracle.sql.CustomDatumFactory;
    import oracle.sql.Datum;
    import oracle.sql.STRUCT;
    import oracle.jpub.runtime.MutableStruct;

    public class JAddress implements CustomDatum, CustomDatumFactory
    {
      public static final String _SQL_NAME = "SCOTT.ADDRESS";
      public static final int _SQL_TYPECODE = OracleTypes.STRUCT;

      public static CustomDatumFactory getFactory()
      { ... }

      /* constructor */
      public JAddress()
      { ... }

      /* CustomDatum interface */
      public Datum toDatum(OracleConnection c) throws SQLException
      { ... }

      /* CustomDatumFactory interface */
      public CustomDatum create(Datum d, int sqlType) throws SQLException
      { ... }

      /* shallow copy method: give object same attributes as argument */
      void shallowCopy(JAddress d) throws SQLException
      { ... }

      /* accessor methods */
      public String getStreet() throws SQLException
      { ... }

      public void setStreet(String street) throws SQLException
      { ... }

      public String getCity() throws SQLException
      { ... }

      public void setCity(String city) throws SQLException
      { ... }

      public String getState() throws SQLException
      { ... }

      public void setState(String state) throws SQLException
      { ... }

      public java.math.BigDecimal getZip() throws SQLException
      { ... }

      public void setZip(java.math.BigDecimal zip) throws SQLException
      { ... }

    }

#### JPublisher-Generated Alternate Reference Class--MyAddressRef.java

Continuing the example in the preceding sections, here is sample code for the JPublisher-generated reference class (`MyAddressRef`, as opposed to `JAddressRef`, because `MyAddress` is the class that `ADDRESS` objects map to). This class also implements `CustomDatum` and `CustomDatumFactory`. Implementation details have been omitted.

    import java.sql.SQLException;
    import oracle.jdbc.driver.OracleConnection;
    import oracle.jdbc.driver.OracleTypes;
    import oracle.sql.CustomDatum;
    import oracle.sql.CustomDatumFactory;
    import oracle.sql.Datum;
    import oracle.sql.REF;
    import oracle.sql.STRUCT;

    public class MyAddressRef implements CustomDatum, CustomDatumFactory
    {
      public static final String _SQL_BASETYPE = "SCOTT.ADDRESS";
      public static final int _SQL_TYPECODE = OracleTypes.REF;

      public static CustomDatumFactory getFactory()
      { ... }

      /* constructor */
      public MyAddressRef()
      { ... }

      /* CustomDatum interface */
      public Datum toDatum(OracleConnection c) throws SQLException
      { ... }

      /* CustomDatumFactory interface */
      public CustomDatum create(Datum d, int sqlType) throws SQLException
      { ... }

      public MyAddress getValue() throws SQLException
      { ... }

      public void setValue(MyAddress c) throws SQLException
      { ... }
    }

#### Extended Custom Object Class--MyAddress.java

Continuing the example in the preceding sections, here is sample code for a `MyAddress` class that subclasses the JPublisher-generated `JAddress` class. The comments in the code show what is inherited from `JAddress`. Implementation details have been omitted.

    import java.sql.SQLException;
    import oracle.sql.CustomDatum;
    import oracle.sql.CustomDatumFactory;
    import oracle.sql.Datum;
    import oracle.sql.STRUCT;
    import oracle.jpub.runtime.MutableStruct;

    public class MyAddress extends JAddress
    {
      /* _SQL_NAME inherited from MyAddress */
      /* _SQL_TYPECODE inherited from MyAddress */

      static _myAddressFactory = new MyAddress();

      public static CustomDatumFactory getFactory()
      {
        return _myAddressFactory;
      }

      /* constructor */
      public MyAddress()
      { super(); }

      /* CustomDatum interface */
      /* toDatum() inherited from JAddress */

      /* CustomDatumFactory interface */
      public CustomDatum create(Datum d, int sqlType) throws SQLException
      { ... }

      /* accessor methods inherited from JAddress */

      /* Additional methods go here.  These additional methods (not shown)
         are the reason that JAddress was extended.
      */
    }

| Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
Library | Service | Contents | Index