Oracle8i JPublisher User's Guide Release 2 (8.1.6) Part Number A81357-01 |
|
This section contains these subsections:
JPublisher is a utility, written entirely in Java, that generates Java classes to represent the following user-defined database entities in your Java program:
varrays
or nested tables)
JPublisher enables you to specify and customize the mapping of database object types, reference types, and collection types (varrays
or nested tables) to Java classes, in a strongly typed paradigm.
JPublisher generates get
and set
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 the database.
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. Therefore, JPublisher generates .sqlj
source files for classes with wrapper methods, that is, classes representing object types or PL/SQL packages. JPublisher generates .java
source files for classes representing REF or collection types. If you ask JPublisher to translate object types without generating wrapper methods, JPublisher will generate .java
source files to represent the object types. You use SQLJ to compile the .sqlj
files; you can use SQLJ or your Java compiler to compile the .java
files.
Instead of using JPublisher-generated classes directly, you can:
oracle.sql
package contains simple generic classes that represent object, REF, and collection types. If these classes meet your requirements, you do not need JPublisher.
JPublisher allows your Java language applications to employ user-defined object types in an Oracle8 server. 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.CustomDatum
interface or the java.sql.SQLData
interface. Either interface
makes it possible to transfer object type instances between the database and
your Java program. For more information on the CustomDatum
interface,
see the Oracle8i JDBC Developer's
Guide and Reference . See The
JDBC 2.0 API, by Sun Microsystems, for more information on the SQLData
interface.
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 generates a single class containing wrapper methods for the top-level subprograms you request.
When you use version 8.1.6 of JPublisher, you should also use version 8.1.6 of SQLJ, because these two products are always installed together. To use all features of JPublisher, you also need:
If you are using only some features of JPublisher, your requirements might be less stringent:
SQLData
classes, and you never use the java.sql.Blob
and java.sql.Clob
classes, you can use JDK version 1.1.1 or higher, rather than JDK 1.2.
CustomDatum
interface, you should be able to use a non-Oracle JDBC driver or a non-Oracle SQLJ implementation. When running code generated by JPublisher, you should even be able to connect to a non-Oracle database; however, JPublisher itself must connect to an Oracle database. Oracle does not test or support configurations that use non-Oracle components.
SQLData
interface (that is, you use JPublisher to generate only classes that implement the CustomDatum
interface), you can use Oracle database version 8.1.5 with JDBC version 8.1.5 and JDK version 1.1.1 or higher.
.sqlj
files; therefore, you do not need to use SQLJ.
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 Net8 and required support files. If you do not have an Oracle client installation, JPublisher can use the Oracle Thin JDBC driver.
JPublisher generates a Java class for each database 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, you additionally must have the SQLJ runtime libraries.
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.
The next section furnishes a general description of the source files that JPublisher creates for object types and PL/SQL packages.
The number of files JPublisher produces depends on whether you request CustomDatum
classes (classes that implement the oracle.sql.CustomDatum
interface) or SQLData
classes (classes that implement the java.sql.SQLData
interface).
The CustomDatum
interface supports database object, REF, and collection types in a strongly typed way. That is, for each specific object, REF, or collection type in the database, there is a corresponding Java type. The SQLData
interface, on the other hand, supports only database object types in a strongly-typed way. All REF types are represented generically as instances of java.sql.Ref
, and all collection types are represented generically as instances of java.sql.Array
. Therefore, JPublisher generates classes for REF and collection types only if it is generating CustomDatum
classes.
When you run JPublisher for a user-defined object type and you request CustomDatum
classes, JPublisher automatically creates the following:
If, instead, you request SQLData classes, JPublisher does not generate the reference class and does not generate classes for nested collection attributes.
When you run JPublisher for a user-defined collection type, you must request CustomDatum
classes. JPublisher automatically creates the following:
This is necessary so that object elements can be materialized in Java whenever an instance of the collection is materialized.
When you run JPublisher for a PL/SQL package, it automatically creates the following:
JPublisher maps the Oracle datatypes of the object's attributes and the PL/SQL package's arguments and function results to Java, according to mappings you specify globally. You can request Oracle-style or JDBC-style mappings. For numeric types, two other mapping styles are available: Object JDBC style and BigDecimal style.
java.lang.String
and java.sql.Blob
, and object types map to SQLData
classes.
CustomDatum
classes.
You can find a more detailed description of the Oracle, JDBC, and Object JDBC mappings in "Type Mappings for All Types (-mapping)" and "Understanding Datatype Mappings".
Here are the basic steps for translating and using code for objects (including nested tables and varray
s) and PL/SQL packages:
REF
types and places them in specified Java packages. JPublisher generates .java
files for REF
, varray
, and nested table classes. If you ask JPublisher to generate wrapper methods, it will generate .sqlj
files for object types and packages. If not, JPublisher will generate .java
files without wrapper methods for object types and will not generate classes for packages (because they contain only wrapper methods).
.sqlj
files, and the Java or SQLJ compiler compiles the .java
files.
Figure 1-1 illustrates the preceding steps.
Here are the three ways in which you can represent user-defined object, collection, and REF
types in your Java program:
SQLData
interface, as described in the JDBC 2.0 API.
JPublisher generates classes for database object types that implement the SQLData
interface. You can also write them by hand. If you write them by hand, your classes must then be registered using a type map.
When you use the SQLData
interface, all REF types are represented generically as instances of java.sql.Ref
, and all collection types are represented generically as instances of java.sql.Array
.
oracle.sql.*
classes.
You can use the oracle.sql.*
classes to represent user-defined types generically. The class oracle.sql.STRUCT
represents all object types, the class oracle.sql.ARRAY
represents all VARRAY
and nested table types, and the class oracle.sql.REF
represents all REF
types. These classes are immutable in the same way that java.lang.String
is.
CustomDatum
interface.
JPublisher generates classes that implement the CustomDatum
interface. You can also write them by hand.
Compared to classes that implement SQLData
, classes that implement CustomDatum
are fundamentally more efficient, because CustomDatum
classes avoid unnecessary conversions to native Java types. For a comparison of the SQLData
and CustomDatum
interfaces, see the Oracle8i JDBC Developer's Guide and Reference.
Compared to oracle.sql.*
classes, classes that implement CustomDatum
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 a CustomDatum
that represents an Address
.
JPublisher generated classes that implement CustomDatum
or SQLData
have additional advantages.
get
and set
methods named after the particular attributes of the object.
CustomDatum
classes representing REF
types are not mutable, because a REF
does not have any subcomponents that could be sensibly modified.
On most operating systems, you invoke JPublisher on the command line. 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:
jpub -user=scott/tiger -input=demoin -numbertypes=oracle -usertypes=oracle -dir=demo -package=corp
You enter the command on one line, allowing it to wrap as necessary. For convenience, this chapter refers to the input file (the file specified by the -input
option) as the INPUT
file.
This command causes JPublisher to connect to the database with username scott
and password tiger
and translate database types 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
directs JPublisher to generate Oracle-specific CustomDatum
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.
This section illustrates a sample JPublisher translation of a simple 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 chapter.
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 command line:
jpub -user=scott/tiger -dir=demo -numbertypes=objectjdbc -builtintypes=jdbc -package=corp -case=mixed -sql=Employee
Because -dir=demo
was specified on the JPublisher command line, the package corp
with the translated class employee
is written to the file:
./demo/corp/Employee.sqlj (UNIX) .\demo\corp\Employee.sqlj (Windows NT)
The Employee.sqlj
class file would contain this code:
package corp; 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; import sqlj.runtime.ref.DefaultContext; import sqlj.runtime.ConnectionContext; import java.sql.Connection; public class Employee implements CustomDatum, CustomDatumFactory { public static final String _SQL_NAME = "SCOTT.EMPLOYEE"; public static final int _SQL_TYPECODE = OracleTypes.STRUCT; #sql static context _Ctx; _Ctx _ctx; MutableStruct _struct; static int[] _sqlType = { 12, 4, 2, 91, 7 }; static CustomDatumFactory[] _factory = new CustomDatumFactory[5]; static final Employee _EmployeeFactory = new Employee(); public static CustomDatumFactory getFactory() { return _EmployeeFactory; } /* constructors */ public Employee() { _struct = new MutableStruct(new Object[5], _sqlType, _factory); try { _ctx = new _Ctx(DefaultContext.getDefaultContext()); } catch (Exception e) { _ctx = null; } } public Employee(ConnectionContext c) throws SQLException { _struct = new MutableStruct(new Object[5], _sqlType, _factory); _ctx = new _Ctx(c == null ? DefaultContext.getDefaultContext() : c); } public Employee(Connection c) throws SQLException { _struct = new MutableStruct(new Object[5], _sqlType, _factory); _ctx = new _Ctx(c); } /* CustomDatum interface */ public Datum toDatum(OracleConnection c) throws SQLException { _ctx = new _Ctx(c); return _struct.toDatum(c, _SQL_NAME); } /* CustomDatumFactory interface */ public CustomDatum create(Datum d, int sqlType) throws SQLException { if (d == null) return null; Employee o = new Employee(); o._struct = new MutableStruct((STRUCT) d, _sqlType, _factory); o._ctx = new _Ctx(((STRUCT) d).getConnection()); 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 int getEmpno() throws SQLException { return ((Integer) _struct.getAttribute(1)).intValue(); } public void setEmpno(int empno) throws SQLException { _struct.setAttribute(1, new Integer(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)).floatValue(); } public void setSalary(float salary) throws SQLException { _struct.setAttribute(4, new Float(salary)); } }
JPublisher also generates an EmployeeRef.java
class. The contents of this file are displayed below.
package corp; 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 EmployeeRef implements CustomDatum, CustomDatumFactory { public static final String _SQL_BASETYPE = "SCOTT.EMPLOYEE"; public static final int _SQL_TYPECODE = OracleTypes.REF; REF _ref; static final EmployeeRef _EmployeeRefFactory = new EmployeeRef(); public static CustomDatumFactory getFactory() { return _EmployeeRefFactory; } /* constructor */ public EmployeeRef() { } /* CustomDatum interface */ public Datum toDatum(OracleConnection c) throws SQLException { return _ref; } /* CustomDatumFactory interface */ public CustomDatum create(Datum d, int sqlType) throws SQLException { if (d == null) return null; EmployeeRef r = new EmployeeRef(); r._ref = (REF) d; return r; } public Employee getValue() throws SQLException { return (Employee) Employee.getFactory().create( _ref.getSTRUCT(), OracleTypes.REF); } public void setValue(Employee c) throws SQLException { _ref.setValue((STRUCT) c.toDatum(_ref.getConnection())); } }
You can find more examples of object mappings in "Example: JPublisher Type Mapping".
|
![]() Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
|