Skip Headers

Oracle9i JPublisher User's Guide
Release 2 (9.2)

Part Number A96658-01
Go To Documentation Library
Home
Go To Product List
Book List
Go To Table Of Contents
Contents
Go To Index
Index

Master Index

Feedback

Go to previous page Go to next page

1
Introduction to JPublisher

This chapter starts with a brief introduction and examples for the JPublisher utility, followed by a more complete overview. The following topics are covered:

If you are new to JPublisher, start with "Invitation to JPublisher". If you have used JPublisher before, you may want to skip ahead to "New JPublisher Features in Oracle9i Release 2".

Introduction to JPublisher Features

This section gives you an introduction to basic features and new features in Oracle9i release 2 (9.2).

Invitation to JPublisher

JPublisher is a utility, written entirely in Java, that generates Java classes to represent the following user-defined database entities in your Java program:

JPublisher enables you to specify and customize the mapping of SQL object types, object reference types, and collection types (VARRAYs or nested tables) to Java classes in a strongly typed paradigm.

JPublisher generates getXXX() and setXXX() accessor methods for each attribute of an object type. If your object types have stored procedures, JPublisher can generate wrapper methods to invoke the stored procedures. A wrapper method is a method that invokes a stored procedure that executes in Oracle9i.

JPublisher can also generate classes for PL/SQL packages. These classes have wrapper methods to invoke the stored procedures in the PL/SQL packages.

The wrapper methods JPublisher generates contain SQLJ code, so when JPublisher generates wrapper methods, it generally produces .sqlj source files. This is true for classes representing PL/SQL packages or object types that define methods, unless you specify (through the -methods option) that JPublisher should not generate wrapper methods.

If no wrapper methods are generated, JPublisher produces .java source files. This is true for classes representing object types without methods, object reference types, or collection types, or for classes where the -methods option is off.

Instead of using JPublisher-generated classes directly, you can:

In addition, JPublisher simplifies access to PL/SQL only types from Java. You can employ predefined or user-defined mappings between PL/SQL and SQL types, as well as make use of PL/SQL conversion functions between such types. With such type correspondences in place, JPublisher can automatically generate all of the required Java and PL/SQL code.

Getting Started with JPublisher

JPublisher is distributed with the Oracle SQLJ translator. If you have installed SQLJ through the Oracle Installer, you should already be set up. If you have manually downloaded a version of Oracle SQLJ, however, you have to go through a few manual steps to ensure you can use SQLJ and JPublisher. You can refer to instructions in the Oracle9i SQLJ Developer's Guide and Reference.

You must ensure the following:

Additionally, if you use JPublisher from release 9.2.0 or later against a 9.2.0 or later Oracle database, the PL/SQL package SYS.SQLJUTL should be installed. If your database is Java-enabled, this is already the case. If not, have your database administrator install the SQL script [Oracle_Home]/sqlj/lib/sqljutl.sql into the SYS schema.


Note:

This rest of this section provides introductory discussion and examples. For more examples, go to [Oracle_Home]/sqlj/demo/jpub in your Oracle installation.


Publishing SQL Object Types

It is straightforward to use JPublisher for publishing SQL objects and packages as Java classes. This section provides examples of this for the OE (Order Entry) schema that is part of the Oracle9i sample schema (see Oracle9i Sample Schemas for detailed information). If you do not have the sample schema installed, but have your own object types or packages that you would like to publish, just replace the user name, password, and object or package names with your own.

Assuming that the password for the OE schema is OE, this is how you can publish the SQL object type CATEGORY_TYP:

jpub -user=OE/OE -sql=CATEGORY_TYP:CategoryTyp

Use the JPublisher -user option to specify the user name (schema name) and password. The -sql option specifies the types and packages to be published. CATEGORY_TYP is the name of the SQL type and, separated by a colon (":"), CategoryTyp is the name of the corresponding Java class to be generated. JPublisher echoes to the standard output the names of the SQL types and packages that it is publishing:

OE.CATEGORY_TYP

When you list the files in your current directory, you will notice that in addition to the file CategoryTyp.java, which you would have expected, JPublisher has also generated a file CategoryTypeRef.java. This represents a strongly typed wrapper for SQL object references to OE.CATEGORY_TYP. Both files are ready to be compiled with the Java compiler javac.

Here is another example, for the type CUSTOMER_TYP, using the shorthand -u (followed by a space) for "-user=" and -s for "-sql=":

jpub -u OE/OE -s CUSTOMER_TYP:CustomerTyp

JPublisher output:

OE.CUSTOMER_TYP
OE.CUST_ADDRESS_TYP
OE.PHONE_LIST_TYP
OE.ORDER_LIST_TYP
OE.ORDER_TYP
OE.ORDER_ITEM_LIST_TYP
OE.ORDER_ITEM_TYP
OE.PRODUCT_INFORMATION_TYP
OE.INVENTORY_LIST_TYP
OE.INVENTORY_TYP
OE.WAREHOUSE_TYP

JPublisher reports a list of SQL object types, because whenever it encounters an object type for the first time (whether it is an attribute, an object reference, or a collection that has element types which themselves are objects or collections), it will automatically generate a wrapper class for that type as well. Two wrapper files are generated for each object type in this example: 1) a Java class, such as CustomerTyp, to represent instances of the object type; and 2) a reference class, such as CustomerTypeRef, to represent references to the object type. You may also have noticed the naming scheme that JPublisher uses by default: the SQL type OE.PRODUCT_INFORMATION_TYP turns into a Java class ProductInformationTyp, for example.

Even though JPublisher automatically generates wrappers for embedded types, it will not do so for subtypes of given object types. In this case, you have to explicitly enumerate all of the subtypes that you want to have published. The CATEGORY_TYP type has three subtypes: LEAF_CATEGORY_TYP, COMPOSITE_CATEGORY_TYP, and CATALOG_TYP. The following is a single wraparound JPublisher command line to publish these object types.

jpub  -u OE/OE  -s COMPOSITE_CATEGORY_TYP:CompositeCategoryTyp
      -s LEAF_CATEGORY_TYP:LeafCategoryTyp,CATALOG_TYP:CatalogTyp

JPublisher output:

OE.COMPOSITE_CATEGORY_TYP
OE.SUBCATEGORY_REF_LIST_TYP
OE.LEAF_CATEGORY_TYP
OE.CATALOG_TYP
OE.CATEGORY_TYP
OE.PRODUCT_REF_LIST_TYP

Note the following:

In case the code generated by JPublisher does not give you the functionality or behavior you want, you can subclass generated wrapper classes in order to override or complement their functionality. Consider the following example:

jpub -u OE/OE -s WAREHOUSE_TYP:JPubWarehouse:MyWarehouse

JPublisher output:

OE.WAREHOUSE_TYP

With this command, JPublisher generates JPubWarehouse.java as well as MyWarehouse.java. The file JPubWarehouse.java is regenerated every time you rerun this command. The file MyWarehouse.java is created in order to be customized by you, and will not be overwritten by future runs of this JPublisher invocation. You can add new methods in MyWarehouse.java, override the method implementations from JPubWarehouse.java, or both. The class used to materialize WAREHOUSE_TYP instances in Java is the specialized class MyWarehouse. If you want user-specific subclasses for all types in an object type hierarchy, you will have to specify "triplets" of the form SQL_TYPE:JPubClass:UserClass as above for all members of the hierarchy.

Now that we have generated and compiled some Java wrapper classes--how do you actually use them in Java programs?

Once you have generated and compiled Java wrapper classes with JPublisher, using them is fairly straightforward, especially if you are programming in SQLJ--just use the object wrappers directly. The following example calls a PL/SQL stored procedure that takes a WAREHOUSE_TYPE instance as an IN OUT parameter:

java.math.BigDecimal location = ...;
java.math.BigDecimal warehouseId = ...;
MyWarehouse w = new MyWarehouse(warehouseId,"Industrial Park",location);
...
#sql { call register_warehouse(:INOUT w) };

In JDBC, you typically register the relationship between the SQL type name and the corresponding Java class in the type map for your connection instance. This is required once per connection, as in the following example:

java.util.Map typeMap = conn.getTypeMap();
typeMap.put("OE.WAREHOUSE_TYP", MyWarehouse.class);
conn.setTypeMap(typeMap);

The following JDBC code corresponds to the #sql statement shown earlier.

CallableStatement cs = conn.prepareCall("{call register_warehouse(?)}");
((OracleCallableStatement)cs).registerOutParameter
                 (1,oracle.jdbc.OracleTypes.STRUCT,"OE.WAREHOUSE_TYP");
cs.setObject(w);
cs.executeUpdate();
w = cs.getObject(1);

Publishing PL/SQL Packages

As shown in the preceding section, it is straightforward to use SQLJ code to call PL/SQL stored procedures or functions. However, you might prefer to encapsulate entire PL/SQL packages as Java classes, and JPublisher also offers functionality for this.

The concept of representing PL/SQL functions and procedures as Java methods presents a problem--arguments to such functions or procedures might use the PL/SQL mode OUT or IN OUT, but there are no equivalent modes for passing arguments in Java. A method that takes an int argument, for example, is not able to modify this argument in such a way that its callers can receive a new value for it. As a workaround, JPublisher generates single-element arrays for OUT and IN OUT arguments. For an array int[] abc, for example, the input value is provided in abc[0], and the modified output value is also returned in abc[0]. A similar pattern is also used by JPublisher when generating code for SQL object type methods.

The following command line publishes the SYS.DBMS_LOB package into Java:

jpub  -u SCOTT/TIGER  -s SYS.DBMS_LOB:DbmsLob

JPublisher output:

SYS.DBMS_LOB

Since DBMS_LOB is publicly visible, we can access it from a different schema, such as SCOTT. Note that this JPublisher invocation creates a SQLJ source file DbmsLob.sqlj that contains the calls to the PL/SQL package. The generated Java methods are actually all instance methods. The idea is that you create an instance of the package using a JDBC connection or a SQLJ connection context and then call the methods on that instance.

Use of Object Types Instead of Java Primitive Numbers

When you examine the generated code, notice that JPublisher has generated java.lang.Integer as arguments to various methods. Using Java object types such as Integer instead of Java primitive types such as int permits you to represent SQL NULL values directly as Java nulls, and JPublisher generates these by default. However, for the DBMS_LOB package we actually prefer int over the object type Integer. The following modified JPublisher invocation accomplishes this through the -numbertypes option.

jpub -numbertypes=jdbc  -u SCOTT/TIGER  -s SYS.DBMS_LOB:DbmsLob

JPublisher output:

SYS.DBMS_LOB

Wrapper Code for Procedures at the SQL Top Level

JPublisher also allows you to generate wrapper code for the functions and procedures at the SQL top level. Use the special package name TOPLEVEL, as in the following example:

jpub  -u SCOTT/TIGER  -s TOPLEVEL:SQLTopLevel

JPublisher output:

SCOTT.<top-level_scope>

You will see a warning if there are no stored functions or procedures in the SQL top-level scope.

If your stored procedures or functions use types that are specific to PL/SQL and not supported from Java, you will receive warning messages and no corresponding Java methods are generated. However, you may be able to map PL/SQL types to corresponding SQL types and their Java counterparts, which will permit JPublisher to generate appropriate Java code, and possibly PL/SQL code, to gain access to these types from Java. (See "Using Datatypes Unsupported by JDBC".)

New JPublisher Features in Oracle9i Release 2

With Oracle9i release 2 (9.2), JPublisher supports virtually all types that can be used with the Oracle JDBC drivers. Additionally, JPublisher facilitates the use of PL/SQL types in stored procedure and object method signatures through PL/SQL conversion support. The following Oracle JDBC types are now directly supported:

Native PL/SQL types can now be more easily accessed by JPublisher code through the automatic generation of PL/SQL wrapper functions and procedures in conjunction with the following mechanisms:

JPublisher now provides improved functionality as well as flexibility in the code it generates, as follows:

JPublisher now reduces the programming effort even further, as follows:

Understanding JPublisher

This section provides a basic understanding of what JPublisher is for and what it accomplishes, covering the following topics:

JPublisher Object Type Mappings and PL/SQL Mappings

JPublisher provides mappings from the following SQL entities to Java classes:

Object Types and JPublisher

JPublisher allows your Java language applications to employ user-defined object types in Oracle9i. If you intend to have your Java-language application access object data, then it must represent the data in a Java format. JPublisher helps you do this by creating the mapping between object types and Java classes, and between object attribute types and their corresponding Java types.

Classes generated by JPublisher implement either the oracle.sql.ORAData interface or the java.sql.SQLData interface, depending on how you set the JPublisher options. Either interface makes it possible to transfer object type instances between the database and your Java program. For more information about the ORAData and SQLData interfaces, see the Oracle9i JDBC Developer's Guide and Reference.

PL/SQL Packages and JPublisher

You might want to call stored procedures in a PL/SQL package from your Java application. The stored procedure can be a PL/SQL subprogram or a Java method that has been published to SQL. Java arguments and functions are passed to and returned from the stored procedure.

To help you do this, you can direct JPublisher to create a class containing a wrapper method for each subprogram in the package. The wrapper methods generated by JPublisher provide a convenient way to invoke PL/SQL stored procedures from Java code or to invoke a Java stored procedure from a client Java program.

If you call PL/SQL code that includes top-level subprograms (subprograms not in any PL/SQL package), JPublisher can generate a class containing wrapper methods for all top-level procedures and functions, or for a subset of the top-level subprograms that you request.

PL/SQL Types and JPublisher

Java programs only permit you to use SQL types when calling PL/SQL stored procedures or functions. Types that are supported by PL/SQL only, such as BOOLEAN, PL/SQL RECORD types, and PL/SQL indexed-by tables cannot be accessed by JDBC programs. One exception to this are scalar PL/SQL indexed-by tables which are currently supported in the client-side JDBC OCI driver only.

JPublisher simplifies the invocation of stored procedures and functions that contain such types: it will automatically create a package with PL/SQL wrapper procedures and functions, as necessary, to convert between signatures containing PL/SQL types and corresponding ones that can be used from Java programs and that reference SQL types only. A mapping has been predefined for the BOOLEAN type. However, in general users will have to provide correspondences and conversions between SQL and PL/SQL in order for JPublisher to incorporate a particular PL/SQL type into its code generation.

JPublisher Processes

JPublisher connects to a database and retrieves descriptions of the SQL object types or PL/SQL packages that you specify on the command line or from an input file. By default, JPublisher connects to the database by using the JDBC OCI driver, which requires an Oracle client installation, including Oracle9i Net and required support files. If you do not have an Oracle client installation, JPublisher can use the Oracle JDBC Thin driver.

JPublisher generates a Java class for each SQL object type it translates. The Java class includes code required to read objects from and write objects to the database. When you deploy the generated JPublisher classes, your JDBC driver installation includes all the necessary runtime files. If you create wrapper methods (Java methods to wrap stored procedures or functions of the SQL object type), JPublisher generates SQLJ source code so you must additionally have the SQLJ runtime libraries.

When you call a wrapper method, the SQL value for the object is sent to the server, along with any IN our IN OUT arguments. Then the method (stored procedure or function) is invoked, and the new object value is returned to the client, along with any OUT or IN OUT arguments. Note that this results in a database round trip. If the method call only performs a simple state change on the object, it will be much more performant to write and use equivalent Java that affects the state change locally.

JPublisher also generates a class for each PL/SQL package it translates. The class includes code to invoke the package methods on the server. IN arguments for the methods are transmitted from the client to the server, and OUT arguments and results are returned from the server to the client. In addition, JPublisher may also generate a PL/SQL wrapper package, if required, for converting signatures containing PL/SQL types into corresponding ones containing SQL types only.

The next section furnishes a general description of the source files that JPublisher creates for object types and PL/SQL packages.

What JPublisher Produces

The number of files JPublisher produces depends on whether you request ORAData classes (classes that implement the oracle.sql.ORAData interface) or SQLData classes (classes that implement the standard java.sql.SQLData interface).

The ORAData interface supports SQL object, object reference, collection, and OPAQUE types in a strongly typed way. That is, for each specific object, object reference, collection, or OPAQUE type in the database, there is a corresponding Java type. The SQLData interface, on the other hand, supports only SQL object types in a strongly typed way. All object reference types are represented generically as java.sql.Ref instances, and all collection types are represented generically as java.sql.Array instances. Therefore, JPublisher generates classes for object reference, collection, and OPAQUE types only if it is generating ORAData classes.

When you run JPublisher for a user-defined object type and you request ORAData classes, JPublisher automatically creates the following:

If you request SQLData classes instead, JPublisher does not generate the object reference class and does not generate classes for nested collection attributes or for OPAQUE attributes.

When you run JPublisher for a user-defined collection type, you must request ORAData classes. JPublisher automatically creates the following:

When you run JPublisher for an OPAQUE type, you must request ORAData classes. JPublisher automatically creates:

When you run JPublisher for a PL/SQL package, it automatically creates the following:

JPublisher Requirements

JPublisher requires that Oracle SQLJ and Oracle JDBC also be installed on your system and in your classpath appropriately. You will need the following libraries (available as .jar or .zip files):

"12" refers to versions for JDK 1.2.x or later; "14" refers to versions for JDK 1.4.x; "11" and "111" refer to versions for JDK 1.1.x. See the Oracle9i SQLJ Developer's Guide and Reference for more information about these files.

When you use an Oracle9i release 2 or later database, then the package SQLJUTL should also be installed and publicly accessible in the SYS schema. If this is not the case, you will see the following warning message when you invoke JPublisher:

Warning: Cannot determine what kind of type is <schema>.<type.> You likely need to install SYS.SQLJUTL. The database returns: ORA-06550: line 1, column 7:

PLS-00201: identifier 'SYS.SQLJUTL' must be declared

In this situation, ask your database administrator to install the SQL file [Oracle Home]/sqlj/lib/sqljutl.sql into the SYS schema and make it publicly accessible. This will avoid the above warning message in the future.

When you use Oracle9i JPublisher, it is typical to use the equivalent version of SQLJ, because these two products are always installed together. To use all features of JPublisher, you also need the following.

If you are using only some features of JPublisher, your requirements might be less stringent:

JPublisher Input and Output

You can specify input options on the command line and in the properties file. In addition to producing .sqlj and .java files for the translated objects, JPublisher writes the names of the translated objects and packages to standard output.

JPublisher Input

"JPublisher Options" describes all the JPublisher options.

In addition, you can use a file known as the INPUT file to specify the object types and PL/SQL packages JPublisher should translate. It also controls the naming of the generated packages and classes. "INPUT File Structure and Syntax" describes INPUT file syntax.

A properties file is an optional text file that you can use to specify options to JPublisher. Specify the names of properties files on the command line, using the -props option. JPublisher processes the properties files as if their contents were inserted, in sequence, on the command line at that point. For additional flexibility, properties files can also be SQL script files where the JPublisher directives are embedded in SQL comments. For more information about this file and its format, see "Properties File Structure and Syntax".

JPublisher Output

JPublisher generates a Java class for each object type that it translates. For each object type, whether an ORAData or a SQLData implementation, JPublisher generates a <type>.sqlj file for the class code (or a <type>.java file if wrapper methods were suppressed or do not exist, or depending on the JPublisher -methods option setting) and a <type>Ref.java file for the code for the REF class of the Java type. For example, if you define an EMPLOYEE SQL object type, JPublisher generates an employee.sqlj file (or an employee.java file) and an employeeRef.java file. Note that the case of Java class names produced by JPublisher is determined by the -case option. See "Case of Java Identifiers (-case)".

For each collection type (nested table or VARRAY) it translates, JPublisher generates a <type>.java file. For nested tables, the generated class has methods to get and set the nested table as an entire array and to get and set individual elements of the table. JPublisher translates collection types when generating ORAData classes, but not when generating SQLData classes. JPublisher can also generate wrapper classes for OPAQUE types. However, OPAQUE types are more typically already pre-mapped to corresponding Java classes that implement the ORAData interface.

For PL/SQL packages, JPublisher generates classes containing wrapper methods as .sqlj files.

When JPublisher generates the class files and wrappers, it also writes the names of the translated types and packages to standard output.

Overview of Datatype Mappings

JPublisher offers different categories of datatype mappings from SQL to Java. JPublisher options to specify these mappings are described below, under "Detailed Descriptions of Options That Affect Datatype Mappings".

Each type mapping option has at least two possible values: jdbc and oracle. The -numbertypes option has two additional alternatives: objectjdbc and bigdecimal.

The following sections describe these categories of mappings. For more information about datatype mappings, see "Details of Datatype Mapping".

JDBC Mapping

The JDBC mapping maps most numeric datatypes to Java primitive types such as int and float, and maps DECIMAL and NUMBER to java.math.BigDecimal. LOB types and other non-numeric built-in types map to standard JDBC Java types such as java.sql.Blob and java.sql.Timestamp. For object types, JPublisher generates SQLData classes. Predefined datatypes that are Oracle extensions (such as BFILE and ROWID) do not have JDBC mappings, so only the oracle.sql.* mapping is supported for these types.

The Java primitive types used in the JDBC mapping do not support null values and do not guard against integer overflow or floating-point loss of precision. If you are using the JDBC mapping and you attempt to call an accessor or method to get an attribute of a primitive type (short, int, float, or double) whose value is null, an exception is thrown. If the primitive type is short or int, then an exception is thrown if the value is too large to fit in a short or int variable.

Object JDBC Mapping

The Object JDBC mapping maps most numeric datatypes to Java wrapper classes such as java.lang.Integer and java.lang.Float, and maps DECIMAL and NUMBER to java.math.BigDecimal. It differs from the JDBC mapping only in that it does not use primitive types.

When you use the Object JDBC mapping, all your returned values are objects. If you attempt to get an attribute whose value is null, a null object is returned.

The Java wrapper classes used in the Object JDBC mapping do not guard against integer overflow or floating-point loss of precision. If you call an accessor method to get an attribute that maps to java.lang.Integer, an exception is thrown if the value is too large to fit.

This is the default mapping for numeric types.

BigDecimal Mapping

BigDecimal mapping, as the name implies, maps all numeric datatypes to java.math.BigDecimal. It supports null values and very large values.

Oracle Mapping

In the Oracle mapping, JPublisher maps any numeric, LOB, or other built-in type to a class in the oracle.sql package. For example, the DATE type is mapped to oracle.sql.DATE, and all numeric types are mapped to oracle.sql.NUMBER. For object, collection, and object reference types, JPublisher generates ORAData classes.

Because the Oracle mapping uses no primitive types, it can represent a null value as a Java null in all cases. Because it uses the oracle.sql.NUMBER class for all numeric types, it can represent the largest numeric values that can be stored in the database.

Other Option Settings

Note that a number of additional option settings influence the nature of the generated code. For example, the option -compatible controls generations of the backward compatible CustomDatum type, while -access specifies the visibility of the generated methods, constructors, and attributes. The option -serializable controls whether a generated object wrapper class implements java.io.Serializable or not.

Creating Types and Packages in the Database

Before you run JPublisher, you must create any new datatypes that you will require in the database. You must also ensure that any PL/SQL packages, methods, and subprograms that you want to invoke from Java are also installed in Oracle9i.

Use the SQL CREATE TYPE statement to create object, VARRAY, and nested table types in the database. JPublisher supports the mapping of these datatypes to Java classes. JPublisher also generates classes for references to object types. REF types are not explicitly declared in SQL. For more information on creating object types, see the Oracle9i SQL Reference.

Use the CREATE PACKAGE and CREATE PACKAGE BODY statements to create PL/SQL packages and store them in the database. PL/SQL furnishes all the capabilities necessary to implement the methods associated with object types. These methods (functions and procedures) reside on the server as part of a user's schema. You can implement the methods in PL/SQL or Java.

Packages are often implemented to provide the following advantages:

For more information on PL/SQL and creating PL/SQL packages, see the PL/SQL User's Guide and Reference.

JPublisher Operation

This section discusses the basic steps in using JPublisher, describes the command-line syntax, and concludes with a more detailed description of a sample translation. The following topics are covered:

Translating and Using PL/SQL Packages and User-Defined Types

This section lists the basic steps, illustrated in Figure 1-1 below, for translating and using code for user-defined types and PL/SQL packages. User-defined types include Oracle objects and Oracle collections--VARRAYs and nested table types.

  1. Create the desired user-defined datatypes and PL/SQL packages in the database.
  2. Have JPublisher generate source code for Java classes that represent PL/SQL packages, user-defined types, and reference types and places them in specified Java packages. JPublisher generates .java files for object reference, VARRAY, and nested table classes. If you instruct JPublisher to generate wrapper methods, it will generate .sqlj files for packages and object types (assuming the object types have methods). If you instruct JPublisher to not generate wrapper methods, it will generate .java files without wrapper methods for object types and will not generate classes for packages (because they contain only wrapper methods). For object types without methods, JPublisher generates .java files in any case.
  3. Import these classes into your application code.
  4. Use the methods in the generated classes to access and manipulate the user-defined types and their attributes.
  5. Compile all classes (the JPublisher-generated code and your code). SQLJ translates and compiles .sqlj and .java files. Or, if you have only .java files, you can simply invoke the Java compiler.
  6. Run your compiled application.

Figure 1-1 Translating and Using JPublisher-Generated Code

Text description of transobj.jpg follows.

Text description of the illustration transobj.jpg

Representing User-Defined Object, Collection, and Reference Types in Java

Here are the three ways to represent user-defined object, collection, object reference, and OPAQUE types in your Java program:

Compared to oracle.sql.* classes, classes that implement ORAData or SQLData are strongly typed. Your connected SQLJ translator will detect an error at translation time if, for example, you mistakenly select a PERSON object into an ORAData object that represents an ADDRESS.

JPublisher-generated classes that implement ORAData or SQLData have additional advantages:

Compared to classes that implement SQLData, classes that implement ORAData are fundamentally more efficient, because ORAData classes avoid unnecessary conversions to native Java types. For a comparison of the SQLData and ORAData interfaces, see the Oracle9i JDBC Developer's Guide and Reference.

Strongly Typed Object References for ORAData Implementations

For Oracle ORAData implementations, JPublisher always generates strongly typed object reference classes as opposed to using the weakly typed oracle.sql.REF class. This is to provide greater type safety and to mirror the behavior in SQL, where object references are strongly typed. The strongly typed classes (with names such as PersonRef for references to PERSON objects) are essentially wrappers for the oracle.sql.REF class.

In these strongly typed REF wrappers, there is a getValue() method that produces an instance of the SQL object that is referenced, in the form of an instance of the corresponding Java class. (Or, in the case of inheritance, perhaps as an instance of a subclass of the corresponding Java class.) For example, if there is a PERSON object type in the database, with a corresponding Person Java class, there will also be a PersonRef Java class. The getValue() method of the PersonRef class would return a Person instance containing the data for a PERSON object in the database. In addition, JPublisher also generates a static cast() method on the PersonRef class, permitting you to convert other typed references to a PersonRef instance.

Whenever a SQL object type has an attribute that is an object reference, the Java class corresponding to the object type would have an attribute that is an instance of a Java class corresponding to the appropriate reference type. For example, if there is a PERSON object with a MANAGER REF attribute, then the corresponding Person Java class will have a ManagerRef attribute.

For standard SQLData implementations, strongly typed object references are not supported--they are not part of the standard. JPublisher does not create a custom reference class; you must use java.sql.Ref or oracle.sql.REF as the reference type.

JPublisher Command-Line Syntax

On most operating systems, you invoke JPublisher on the command line, typing jpub followed by a series of options settings as follows:

jpub -option1=value1 -option2=value2 ...

JPublisher responds by connecting to the database and obtaining the declarations of the types or packages you specify, then generating one or more custom Java files and writing the names of the translated object types or PL/SQL packages to standard output.

Here is an example of a command that invokes JPublisher (single wraparound command line):

jpub -user=scott/tiger -input=demoin -numbertypes=oracle -usertypes=oracle 
-dir=demo -package=corp

Enter the command on one command line, allowing it to wrap as necessary. For clarity, this chapter refers to the input file (the file specified by the -input option) as the INPUT file (to distinguish it from any other kinds of input files).

This command directs JPublisher to connect to the database with username SCOTT and password TIGER and translate datatypes to Java classes, based on instructions in the INPUT file demoin. The -numbertypes=oracle option directs JPublisher to map object attribute types to Java classes supplied by Oracle, and the -usertypes=oracle option directs JPublisher to generate Oracle-specific ORAData classes. JPublisher places the classes that it generates in the package corp in the directory demo.

"JPublisher Options" describes each of these options in more detail.


Notes:
  • No spaces are permitted around the equals sign (=).
  • If you execute JPublisher without any options on the command line, it displays an option list and then terminates.

Sample JPublisher Translation

This section provides a sample JPublisher translation of an object type. At this point, do not worry about the details of the code JPublisher generates. You can find more information about JPublisher input and output files, options, datatype mappings, and translation later in this manual.

Create the object type EMPLOYEE:

CREATE TYPE employee AS OBJECT
(
    name       VARCHAR2(30),
    empno      INTEGER,
    deptno     NUMBER,
    hiredate   DATE,
    salary     REAL
);

The INTEGER, NUMBER, and REAL types are all stored in the database as NUMBER types, but after translation they have different representations in the Java program, based on your choice for the value of the -numbertypes option.

JPublisher translates the types according to the following command line:

jpub -user=scott/tiger -dir=demo -numbertypes=objectjdbc -builtintypes=jdbc 
-package=corp -case=mixed -sql=Employee

This is a single wraparound command line. "JPublisher Options" describes each of these options in detail.

Note that because the EMPLOYEE object type does not define any methods, JPublisher will generate a .java file, not a .sqlj file.

Because -dir=demo and -package=corp were specified on the JPublisher command line, the translated class Employee is written to Employee.java in the following location:

./demo/corp/Employee.java           (UNIX)
.\demo\corp\Employee.java           (Windows NT)

The Employee.java class file would contain the code below.


Note:

The details of the code JPublisher generates are subject to change. In particular, non-public methods, non-public fields, and all method bodies may be generated differently.


package corp;

import java.sql.SQLException;
import java.sql.Connection;
import oracle.jdbc.OracleTypes;
import oracle.sql.ORAData;
import oracle.sql.ORADataFactory;
import oracle.sql.Datum;
import oracle.sql.STRUCT;
import oracle.jpub.runtime.MutableStruct;

public class Employee implements ORAData, ORADataFactory
{
  public static final String _SQL_NAME = "SCOTT.EMPLOYEE";
  public static final int _SQL_TYPECODE = OracleTypes.STRUCT;

  protected MutableStruct _struct;

  private static int[] _sqlType =  { 12,4,2,91,7 };
  private static ORADataFactory[] _factory = new ORADataFactory[5];
  protected static final Employee _EmployeeFactory = new Employee(false);

  public static ORADataFactory getORADataFactory()
  { return _EmployeeFactory; }

  /* constructor */
  protected Employee(boolean init)
  { if(init) _struct = new MutableStruct(new Object[5], _sqlType, _factory); }
  public Employee()
  { this(true); }
  public Employee(String name, Integer empno, java.math.BigDecimal deptno, 
java.sql.Timestamp hiredate, Float salary) 
   throws SQLException
  { this(true);
    setName(name);
    setEmpno(empno);
    setDeptno(deptno);
    setHiredate(hiredate);
    setSalary(salary);
  }

  /* ORAData interface */
  public Datum toDatum(Connection c) throws SQLException
  {
    return _struct.toDatum(c, _SQL_NAME);
  }

  /* ORADataFactory interface */
  public ORAData create(Datum d, int sqlType) throws SQLException
  { return create(null, d, sqlType); }
  protected ORAData create(Employee o, Datum d, int sqlType) throws SQLException
  {
    if (d == null) return null; 
    if (o == null) o = new Employee(false);
    o._struct = new MutableStruct((STRUCT) d, _sqlType, _factory);
    return o;
  }
  /* accessor methods */
  public String getName() throws SQLException
  { return (String) _struct.getAttribute(0); }

  public void setName(String name) throws SQLException
  { _struct.setAttribute(0, name); }

  public Integer getEmpno() throws SQLException
  { return (Integer) _struct.getAttribute(1); }

  public void setEmpno(Integer empno) throws SQLException
  { _struct.setAttribute(1, empno); }

  public java.math.BigDecimal getDeptno() throws SQLException
  { return (java.math.BigDecimal) _struct.getAttribute(2); }

  public void setDeptno(java.math.BigDecimal deptno) throws SQLException
  { _struct.setAttribute(2, deptno); }

  public java.sql.Timestamp getHiredate() throws SQLException
  { return (java.sql.Timestamp) _struct.getAttribute(3); }

  public void setHiredate(java.sql.Timestamp hiredate) throws SQLException
  { _struct.setAttribute(3, hiredate); }

  public Float getSalary() throws SQLException
  { return (Float) _struct.getAttribute(4); }

  public void setSalary(Float salary) throws SQLException
  { _struct.setAttribute(4, salary); }

}
Code Generation Notes

JPublisher also generates an EmployeeRef.java class. The source code is displayed here:


package corp;

import java.sql.SQLException;
import java.sql.Connection;
import oracle.jdbc.OracleTypes;
import oracle.sql.ORAData;
import oracle.sql.ORADataFactory;
import oracle.sql.Datum;
import oracle.sql.REF;
import oracle.sql.STRUCT;

public class EmployeeRef implements ORAData, ORADataFactory
{
  public static final String _SQL_BASETYPE = "SCOTT.EMPLOYEE";
  public static final int _SQL_TYPECODE = OracleTypes.REF;

  REF _ref;

private static final EmployeeRef _EmployeeRefFactory = new EmployeeRef();

  public static ORADataFactory getORADataFactory()
  { return _EmployeeRefFactory; }
  /* constructor */
  public EmployeeRef()
  {
  }

  /* ORAData interface */
  public Datum toDatum(Connection c) throws SQLException
  {
    return _ref;
  }

  /* ORADataFactory interface */
  public ORAData create(Datum d, int sqlType) throws SQLException
  {
    if (d == null) return null;
    EmployeeRef r = new EmployeeRef();
    r._ref = (REF) d;
    return r;
  }

  public static EmployeeRef cast(ORAData o) throws SQLException
  {
     if (o == null) return null;
     try { return (EmployeeRef) getORADataFactory().create(o.toDatum(null), 
OracleTypes.REF); }
     catch (Exception exn)
     { throw new SQLException("Unable to convert "+o.getClass().getName()+" to 
EmployeeRef: "+exn.toString()); }
  }

  public Employee getValue() throws SQLException
  {
     return (Employee) Employee.getORADataFactory().create(
       _ref.getSTRUCT(), OracleTypes.REF);
  }

  public void setValue(Employee c) throws SQLException
  {
    _ref.setValue((STRUCT) c.toDatum(_ref.getJavaSqlConnection()));
  }
}

Note that JPublisher in Oracle9i release 2 and higher also generates a public static cast() method to cast from other strongly typed references into a strongly typed reference instance.

You can find more examples of object mappings in "Example: JPublisher Object Attribute Mapping".


Go to previous page Go to next page
Oracle
Copyright © 1999, 2002 Oracle Corporation.

All Rights Reserved.
Go To Documentation Library
Home
Go To Product List
Book List
Go To Table Of Contents
Contents
Go To Index
Index

Master Index

Feedback