Skip Headers

Oracle9i Application Developer's Guide - Object-Relational Features
Release 2 (9.2)

Part Number A96594-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

3
Object Support in Oracle Programming Environments

In Oracle9i, you can create object types with SQL data definition language (DDL) commands, and you can manipulate objects with SQL data manipulation language (DML) commands. Object support is built into Oracle's application programming environments:

SQL

Oracle SQL DDL provides the following support for object types:

Oracle SQL DML provides the following support for object types:

PL/SQL

Object types and subtypes can be used in PL/SQL procedures and functions in most places where built-in types can appear.

The parameters and variables of PL/SQL functions and procedures can be of object types.

You can implement the methods associated with object types in PL/SQL. These methods (functions and procedures) reside on the server as part of a user's schema.

See Also:

For a complete description of PL/SQL, see the PL/SQL User's Guide and Reference.

Oracle Call Interface (OCI)

LNOCI is a set of C library functions that applications can use to manipulate data and schemas in an Oracle database. OCI supports both traditional 3GL and object-oriented techniques for database access, as explained in the following sections.

An important component of OCI is a set of calls to manage a workspace called the object cache. The object cache is a memory block on the client side that allows programs to store entire objects and to navigate among them without additional round trips to the server.

The object cache is completely under the control and management of the application programs using it. The Oracle server has no access to it. The application programs using it must maintain data coherency with the server and protect the workspace against simultaneous conflicting access.

LNOCI provides functions to

LNOCI improves concurrency by allowing individual objects to be locked. It improves performance by supporting complex object retrieval.

LNOCI developers can use the object type translator to generate the C datatypes corresponding to a Oracle object types.

See Also:

Oracle Call Interface Programmer's Guide for more information about using objects with OCI

Associative Access in OCI Programs

Traditionally, 3GL programs manipulate data stored in a relational database by executing SQL statements and PL/SQL procedures. Data is usually manipulated on the server without incurring the cost of transporting the data to the client(s). OCI supports this associative access to objects by providing an API for executing SQL statements that manipulate object data. Specifically, OCI enables you to:

Navigational Access in OCI Programs

In the object-oriented programming paradigm, applications model their real-world entities as a set of inter-related objects that form graphs of objects. The relationships between objects are implemented as references. An application processes objects by starting at some initial set of objects, using the references in these initial objects to traverse the remaining objects, and performing computations on each object. OCI provides an API for this style of access to objects, known as navigational access. Specifically, OCI enables you to:

Object Cache

To support high-performance navigational access of objects, OCI runtime provides an object cache for caching objects in memory. The object cache supports references (REFs) to database objects in the object cache, the database objects can be identified (that is, pinned) through their references. Applications do not need to allocate or free memory when database objects are loaded into the cache, because the object cache provides transparent and efficient memory management for database objects.

Also, when database objects are loaded into the cache, they are transparently mapped into the host language representation. For example, in the C programming language, the database object is mapped to its corresponding C structure. The object cache maintains the association between the object copy in the cache and the corresponding database object. Upon transaction commit, changes made to the object copy in the cache are propagated automatically to the database.

The object cache maintains a fast look-up table for mapping REFs to objects. When an application de-references a REF and the corresponding object is not yet cached in the object cache, the object cache automatically sends a request to the server to fetch the object from the database and load it into the object cache. Subsequent de-references of the same REF are faster because they become local cache access and do not incur network round-trips. To notify the object cache that an application is accessing an object in the cache, the application pins the object; when it is finished with the object, it unpins it. The object cache maintains a pin count for each object in the cache. The count is incremented upon a pin call and decremented upon an unpin call. When the pin count goes to zero, it means the object is no longer needed by the application. The object cache uses a least-recently used (LRU) algorithm to manage the size of the cache. When the cache reaches the maximum size, the LRU algorithm frees candidate objects with a pin count of zero.

Building an OCI Program that Manipulates Objects

When you build an OCI program that manipulates objects, you must complete the following general steps:

  1. Define the object types that correspond to the application objects.
  2. Execute the SQL DDL statements to populate the database with the necessary object types.
  3. Represent the object types in the host language format.

    For example, to manipulate instances of the object types in a C program, you must represent these types in the C host language format. You can do this by representing the object types as C structs. You can use a tool provided by Oracle called the Object Type Translator (OTT) to generate the C mapping of the object types. The OTT puts the equivalent C structs in header (*.h) files. You include these *.h files in the *.c files containing the C functions that implement the application.

  4. Construct the application executable by compiling and linking the application's *.c files with the OCI library.

    See Also:

    "LNOCI Tips and Techniques for Objects"

Defining User-Defined Constructors in C

When defining a user-defined constructor in C, you must specify SELF (and you may optionally specify SELF TDO) in the PARAMETERS clause. On entering the C function, the attributes of the C structure that the object maps to are all initialized to NULL. The value returned by the function is mapped to an instance of the user-defined type.

For example:

CREATE OR REPLACE TYPE person AS OBJECT
(
    name VARCHAR2(30),
    CONSTRUCTOR FUNCTION person(name VARCHAR2) RETURN SELF AS RESULT
);

CREATE OR REPLACE TYPE BODY person IS
    CONSTRUCTOR FUNCTION person(name VARCHAR2) RETURN SELF AS RESULT
    IS EXTERNAL NAME "cons_person_typ" LIBRARY person_lib WITH CONTEXT
    PARAMETERS(context, SELF, name OCIString, name INDICATOR sb4);
end;

The SELF parameter is mapped like an IN parameter, so in the case of a NOT FINAL type, it is mapped to (dvoid *), not (dvoid **).

The return value's TDO must match the TDO of SELF and is therefore implicit. The return value can never be null, so the return indicator is implicit as well.

Oracle C++ Call Interface (OCCI)

The Oracle C++ Call Interface (OCCI) is a C++ API that enables you to use the object-oriented features, native classes, and methods of the C++ programing language to access the Oracle database.

The OCCI interface is modeled on the JDBC interface and, like the JDBC interface, is easy to use. OCCI itself is built on top of OCI and provides the power and performance of OCI using an object-oriented paradigm.

LNOCI is a C API to the Oracle database. It supports the entire Oracle feature set and provides efficient access to both relational and object data, but it can be challenging to use--particularly if you want to work with complex, object datatypes. Object types are not natively supported in C, and simulating them in C is not easy. OCCI addresses this by providing a simpler, object-oriented interface to the functionality of OCI. It does this by defining a set of wrappers for OCI. By working with these higher-level abstractions, developers can avail themselves of the underlying power of OCI to manipulate objects in the server through an object-oriented interface that is significantly easier to program.

The Oracle C++ Call Interface, OCCI, can be roughly divided into three sets of functionalities, namely:

OCCI Associative Relational and Object Interfaces

The associative relational API and object classes provide SQL access to the database. Through these interfaces, SQL is executed on the server to create, manipulate, and fetch object or relational data. Applications can access any dataype on the server, including the following:

The OCCI Navigational Interface

The navigational interface is a C++ interface that lets you seamlessly access and modify object-relational data in the form of C++ objects without using SQL. The C++ objects are transparently accessed and stored in the database as needed.

With the OCCI navigational interface, you can retrieve an object and navigate through references from that object to other objects. Server objects are materialized as C++ class instances in the application cache.

An application can use OCCI object navigational calls to perform the following functions on the server's objects:

Pro*C/C++

The Oracle Pro*C/C++ precompiler allows programmers to use user-defined datatypes in C and C++ programs.

Pro*C developers can use the Object Type Translator to map Oracle object types and collections into C datatypes to be used in the Pro*C application.

Pro*C provides compile time type checking of object types and collections and automatic type conversion from database types to C datatypes.

Pro*C includes an EXEC SQL syntax to create and destroy objects and offers two ways to access objects in the server:

Associative Access in Pro*C/C++

For background information on associative access, see "Associative Access in OCI Programs".

Pro*C/C++ offers the following capabilities for associative access to objects:

Navigational Access in Pro*C/C++

For background information on navigational access, see "Navigational Access in OCI Programs".

Pro*C/C++ offers the following capabilities to support a more object-oriented interface to objects:

Converting Between Oracle Types and C Types

The C representation for objects that is generated by the Oracle Type Translator (OTT) uses OCI types whose internal details are hidden, such as LNOCIString and LNOCINumber for scalar attributes. Collection types and object references are similarly represented using LNOCITable, LNOCIArray, and LNOCIRef types. While using these "opaque" types insulates you from changes to their internal formats, using such types in a C or C++ application is cumbersome. Pro*C/C++ provides the following ease-of-use enhancements to simplify use of OCI types in C and C++ applications:

Oracle Type Translator (OTT)

The Oracle type translator (OTT) is a program that automatically generates C language structure declarations corresponding to object types. OTT makes it easier to use the Pro*C precompiler and the OCI server access package.

See Also:

For complete information about OTT, see Oracle Call Interface Programmer's Guide and Pro*C/C++ Precompiler Programmer's Guide.

Oracle Objects For OLE (OO4O)

Oracle Objects for OLE (OO4O)--for Visual Basic, Excel, ActiveX, and Active Server Pages--provides full support for accessing and manipulating instances of REFs, value instances, variable-length arrays (VARRAYs), and nested tables in an Oracle database server.

See Also:

OO4O online help for detailed information about using OO4O with Oracle objects.

Figure 3-1 illustrates the containment hierarchy for value instances of all types in OO4O.

Figure 3-1 Supported Oracle Datatypes

Text description of adobj017.gif follows
Text description of the illustration adobj017.gif


Instances of these types can be fetched from the database or passed as input or output variables to SQL statements and PL/SQL blocks, including stored procedures and functions. All instances are mapped to COM Automation Interfaces that provide methods for dynamic attribute access and manipulation. These interfaces may be obtained from:

Representing Objects in Visual Basic (OraObject)

The OraObject interface is a representation of an Oracle embedded object or a value instance. It contains a collection interface (OraAttributes) for accessing and manipulating (updating and inserting) individual attributes of a value instance. Individual attributes of an OraAttributes collection interface can be accessed by using a subscript or the name of the attribute.

The following Visual Basic example illustrates how to access attributes of the Address object in the person_tab table:

Dim Address OraObject
Set Person = OraDatabase.CreateDynaset("select * from person_tab", 0&)
Set Address = Person.Fields("Addr").Value
msgbox Address.Zip
msgbox.Address.City

Representing REFs in Visual Basic (OraRef)

The OraRef interface represents an Oracle object reference (REF) as well as referenceable objects in client applications. The object attributes are accessed in the same manner as attributes of an object represented by the OraObject interface. OraRef is derived from an OraObject interface by means of the containment mechanism in COM. REF objects are updated and deleted independent of the context they originated from, such as Dynasets. The OraRef interface also encapsulates the functionality for navigating through graphs of objects utilizing the Complex Object Retrieval Capability (COR) in OCI, described in "Pre-Fetching Related Objects (Complex Object Retrieval)".

Representing VARRAYs and Nested Tables in Visual Basic (OraCollection)

The OraCollection interface provides methods for accessing and manipulating Oracle collection types, namely variable-length arrays (VARRAYs) and nested tables in OO4O. Elements contained in a collection are accessed by subscripts.

The following Visual Basic example illustrates how to access attributes of the EnameList object from the department table:

Dim EnameList OraCollection
Set Person = OraDatabase.CreateDynaset("select * from department", 0&)
set EnameList = Department.Fields("Enames").Value
'access all elements of the EnameList VArray
for I=1 to I=EnameList.Size
   msgbox EnameList(I)
Next I

Java: JDBC, Oracle SQLJ, JPublisher, and SQLJ Object Types

Java has emerged as a powerful, modern object-oriented language that provides developers with a simple, efficient, portable, and safe application development platform. Oracle provides two ways to integrate Oracle object features with Java: JDBC and Oracle SQLJ. These interfaces enable you both to access SQL data from Java and to provide persistent database storage for Java objects.

JDBC Access to Oracle Object Data

JDBC (Java Database Connectivity) is a set of Java interfaces to the Oracle server. Oracle provides tight integration between objects and JDBC. You can map SQL types to Java classes with considerable flexibility.

Oracle's JDBC:

Version 2.0 of the JDBC specification supports object-relational constructs such as user-defined (object) types. JDBC materializes Oracle objects as instances of particular Java classes. Using JDBC to access Oracle objects involves creating the Java classes for the Oracle objects and populating these classes. You can either:

SQLJ Access to Oracle Object Data

SQLJ provides access to server objects using SQL statements embedded in the Java code:

Choosing a Data Mapping Strategy

Oracle SQLJ supports either strongly typed or weakly typed Java representations of object types, reference types (REFs), and collection types (varrays and nested tables) to be used in iterators or host expressions.

Strongly typed representations use a custom Java class that corresponds to a particular object type, REF type, or collection type and must implement the interface oracle.sql.CustomDatum. The Oracle JPublisher utility can automatically generate such custom Java classes.

Weakly typed representations use the class oracle.sql.STRUCT (for objects), oracle.sql.REF (for references), or oracle.sql.ARRAY (for collections).

Using JPublisher to Create Java Classes for JDBC and SQLJ Programs

Oracle lets you map Oracle object types, reference types, and collection types to Java classes and preserve all the benefits of strong typing. You can:

We recommend that you use JPublisher and subclass when the generated classes do not do everything you need.

What JPublisher Produces

When you run JPublisher for a user-defined object type, it automatically creates the following:

When you run JPublisher for a user-defined collection type, it automatically creates the following:

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

See Also:

The Oracle9i JPublisher User's Guide for more information about using JPublisher.

Java Object Storage

JPublisher enables you to construct Java classes that map to existing SQL types. You can then access the SQL types from a Java application using JDBC.

With Oracle9i, you can now also go in the other direction: that is, you can create SQL types that map to existing Java classes. This capability enables you to provide persistent storage for Java objects. Such SQL types are called SQL types of Language Java, or SQLJ object types. They can be used as the type of an object, an attribute, a column, or a row in an object table. You can navigationally access objects of such types--Java objects--through either object references or foreign keys, and you can query and manipulate such objects from SQL.

You create SQLJ types with a CREATE TYPE statement as you do other user-defined SQL types. For SQLJ types, two special elements are added to the CREATE TYPE statement:

For example:

CREATE TYPE person_t AS OBJECT
  EXTERNAL NAME 'Person' LANGUAGE JAVA
  USING SQLData (
    ss_no NUMBER (9) EXTERNAL NAME 'socialSecurityNo',
    name varchar(100) EXTERNAL NAME 'name',
    address full_address EXTERNAL NAME 'addrs',
    birth_date date EXTERNAL NAME 'birthDate',
    MEMBER FUNCTION age () RETURN NUMBER EXTERNAL NAME 'age () return int',
    MEMBER FUNCTION address RETURN full_address EXTERNAL NAME 'get_address ()
      return long_address',
    STATIC create RETURN person_t EXTERNAL NAME 'create () return Person',
    STATIC create (name VARCHAR(100), addrs full_address, bDate DATE)
      RETURN person_t EXTERNAL NAME 'create (java.lang.String, Long_address,
      oracle.sql.date) return Person',
    ORDER FUNCTION compare (in_person person_t) RETURN NUMBER 
      EXTERNAL NAME 'isSame (Person) return int'
  )
/

SQLJ types use the corresponding Java class as the body of the type; you do not specify a type body in SQL to contain implementations of the type's methods as you do with ordinary object types.

Representing SQLJ Types to the Server

How a SQLJ type is represented to the server and stored depends on the interfaces implemented by the corresponding Java class. Currently, Oracle supports a representation of SQLJ types only for Java classes that implement a SQLData, CustomDatum, or ORAData interface. These are represented to the server and are accessible through SQL. A representation for Java classes that implement the java.io.Serializable interface is not currently supported.

In a SQL representation, the attributes of the type are stored in columns like attributes of ordinary object types. With this representation, all attributes are public because objects are accessed and manipulated through SQL statements, but you can use triggers and constraints to ensure the consistency of the object data.

For a SQL representation, the USING clause must specify either SQLData, CustomDatum, or ORAData, and the corresponding Java class must implement one of those interfaces. The EXTERNAL NAME clause for attributes is optional.

Creating SQLJ Object Types

The SQL statements to create SQLJ types and specify their mappings to Java are placed in a file called a deployment descriptor. Related SQL constraints and privileges are also specified in this file. The types are created when the file is executed.

Below is an overview of the process of creating SQL versions of Java types/classes:

  1. Design the Java types.
  2. Generate the Java classes.
  3. Create the SQLJ object type statements.
  4. Construct the JAR file. This is a single file that contains all the classes needed.
  5. Using the loadjava utility, install the Java classes defined in the JAR file.
  6. Execute the statements to create the SQLJ object types.

Sample SQLJ Object Type Mapping

The following code defines two Java classes. Then follows code that shows corresponding CREATE TYPE statements of the sort that go in a deployment descriptor. The code defines a one-to-one mapping of Java classes to SQL types, with all Java fields mapped to attributes in the SQL types.

package Examples;

import java.sql.*;
//import oracle.jdbc2.*;

// Java Address class based on SQLJ part 2

public class Address implements SQLData {
  protected String street;
  protected String city;
  protected String state;
  protected int zipCode;
  protected String sql_type;
  public static int recommendedWidth = 250;

  public Address () {
    street = "Unknown";
    city = "somewhere";
    state = "nowhere";
    zipCode = 0;
  }

  public Address (String st, String cit, String stt, int zip) {
    street = st;
    state = stt;
    city = cit;
    zipCode = zip;
  }

  protected static String strip(String in) {

    int len;
    int i;

    if (in == null) return in;
    if (in.charAt (0) != ' ') return in;

    len = in.length();

    for (i = 0; i < len && in.charAt(i) == ' '; i++) {}

    if (i == len) return null;
    
    return in.substring (i, len);
  }

  public String getSQLTypeName() throws SQLException
  {
    return sql_type;
  }

  public void readSQL(SQLInput stream, String typeName)
    throws SQLException
  {
    sql_type = typeName;

    street = stream.readString();
    city = stream.readString();
    state = stream.readString();
    zipCode = stream.readInt();
  }

  public void writeSQL(SQLOutput stream)
    throws SQLException
  {
    stream.writeString(street);
    stream.writeString(city);
    stream.writeString(state);
    stream.writeInt(zipCode);
  }

  public static Address create () {
    return new Address() ;
  }

  public static Address create (String st, String cit, String stt, int zp) {
    return new Address(st, cit, stt, zp);
  }

  public String toString() {
    return "Street" + street + "City" + city + "State" + state + zipCode ;
  }

  public Address removeLeadingBlanks () {
    // The definition of the Misc class has been omitted in this example.
    // Misc is fully described in the SQLJ part 2 specification.

    street = strip (street);
    city = strip (city) ;
    state = strip (state);
    return this;
  }
}
// create LongAddress as subclass of Address

public class LongAddress extends Address {

  protected String street2;
  protected String country;
  protected String addrCode ;

  public LongAddress () {
  
    super();
    street2 = " ";
    country = " ";
    addrCode = " ";
  }

  public LongAddress 
  (String st, String st2, String ct, String stt, String cntry, String cd){
    street = st;
    street2 = st2;
    state = stt;
    country = cntry;
    city = ct;
    zipCode = 0;
    addrCode = cd;
  }

  public void readSQL(SQLInput stream, String typeName)
    throws SQLException
  {
    sql_type = typeName;

    street = stream.readString();
    city = stream.readString();
    state = stream.readString();
    zipCode = stream.readInt();
    street2 = stream.readString();
    country = stream.readString();
    addrCode = stream.readString();
    
  }

  public void writeSQL(SQLOutput stream)
    throws SQLException
  {
    stream.writeString(street);
    stream.writeString(city);
    stream.writeString(state);
    stream.writeInt(zipCode);
    stream.writeString(street2);
    stream.writeString(country);
    stream.writeString(addrCode);
  }

  public static Address create () {
    return new LongAddress();
  }

  public static Address create (
    String st, String st2, String ct, String stt, String cntry, String cd){
    return new LongAddress (st, st2, ct, stt, cntry, cd);
  }

  public String toString () {    
    if (zipCode != 0)
      return "Street " + street + "City " + city + "State " + state +
        "Zip" + zipCode + "USA";
    else 
      return "Street " + street + street2 + "City " + city + "State " +
        state + "Country " + country + addrCode ;
  }

  public Address removeLeadingBlanks () {
    // Misc class is not defined please refer to the SQLJ specs
    street = strip (street);
    street2 = strip (street2);
    city = strip (city) ;
    state = strip (state);
    country = strip (country);
    addrCode = strip (addrCode);
    return this;
  }
}

The following code might go in a deployment descriptor to create SQLJ types to correspond to the Java classes defined in the preceding code.

CREATE TYPE address_t AS OBJECT
  EXTERNAL NAME 'Examples.Address' LANGUAGE JAVA 
  USING SQLData(
    street_attr varchar(250) EXTERNAL NAME 'street',
    city_attr varchar(50) EXTERNAL NAME 'city',
    state varchar(50) EXTERNAL NAME 'state',
    zip_code_attr number EXTERNAL NAME 'zipCode',
    STATIC FUNCTION recom_width RETURN NUMBER
      EXTERNAL VARIABLE NAME 'recommendedWidth',
    STATIC FUNCTION create_address RETURN address_t
      EXTERNAL NAME 'create() return Examples.Address',
    STATIC FUNCTION construct RETURN address_t
      EXTERNAL NAME 'create() return Examples.Address',
    STATIC FUNCTION create_address (street VARCHAR, city VARCHAR, 
        state VARCHAR, zip NUMBER) RETURN address_t
      EXTERNAL NAME 'create (java.lang.String, java.lang.String,
        java.lang.String, int) return Examples.Address',
    STATIC FUNCTION construct (street VARCHAR, city VARCHAR, 
        state VARCHAR, zip NUMBER) RETURN address_t
      EXTERNAL NAME 
        'create (java.lang.String, java.lang.String, java.lang.String, int) 
        return Examples.Address',
    MEMBER FUNCTION to_string RETURN VARCHAR
      EXTERNAL NAME 'tojava.lang.String() return java.lang.String',
    MEMBER FUNCTION strip RETURN SELF AS RESULT 
      EXTERNAL NAME 'removeLeadingBlanks () return Examples.Address'
  ) NOT FINAL;
/
CREATE OR REPLACE TYPE long_address_t
UNDER address_t
EXTERNAL NAME 'Examples.LongAddress' LANGUAGE JAVA 
USING SQLData(
    street2_attr VARCHAR(250) EXTERNAL NAME 'street2',
    country_attr VARCHAR (200) EXTERNAL NAME 'country',
    address_code_attr VARCHAR (50) EXTERNAL NAME 'addrCode',    
    STATIC FUNCTION create_address RETURN long_address_t 
      EXTERNAL NAME 'create() return Examples.LongAddress',
    STATIC FUNCTION  construct (street VARCHAR, city VARCHAR, 
        state VARCHAR, country VARCHAR, addrs_cd VARCHAR) 
      RETURN long_address_t 
      EXTERNAL NAME 
        'create(java.lang.String, java.lang.String, java.lang.String, 
        java.lang.String, java.lang.String) return Examples.LongAddress',
    STATIC FUNCTION construct RETURN long_address_t
      EXTERNAL NAME 'Examples.LongAddress() return Examples.LongAddress',
    STATIC FUNCTION create_longaddress (
      street VARCHAR, city VARCHAR, state VARCHAR, country VARCHAR, 
      addrs_cd VARCHAR) return long_address_t
      EXTERNAL NAME 
        'Examples.LongAddress (java.lang.String, java.lang.String, 
        java.lang.String, java.lang.String, java.lang.String) 
        return Examples.LongAddress',
    MEMBER FUNCTION get_country RETURN VARCHAR
      EXTERNAL NAME 'country_with_code () return java.lang.String'
  );
/

More About Mapping

Evolving SQLJ Types

The ALTER TYPE statement enables you to evolve a type by, for example, adding or dropping attributes or methods.

When a SQLJ type is evolved, an additional validation is performed to check the mapping between the class and the type. If the class and the evolved type match, the type is marked valid. Otherwise, the type is marked as pending validation.

Being marked as pending validation is not the same as being marked invalid. A type that is pending validation can still be manipulated with ALTER TYPE and GRANT statements, for example.

If a type that has a SQL representation is marked as pending evaluation, you can still access tables of that type using any DML or SELECT statement that does not require a method invocation.

You cannot, however, execute DML or SELECT statements on tables of a type that has a serializable representation and has been marked as pending validation. Data of a serializable type can be accessed only navigationally, through method invocations. These are not possible with a type that is pending validation. However, you can still re-evolve the type until it passes validation.

See Also:

"Type Evolution"

Constraints

For SQLJ types having a SQL representation, the same constraints can be defined as for ordinary object types.

Constraints are defined on tables, not on types, and are defined at the column level. The following constraints are supported for SQLJ types having a SQL representation:

The IS OF TYPE constraint on column substitutability is supported, too, for SQLJ types having a SQL representation.

See Also:

"Constraining Substitutability"

Querying SQLJ Objects

SQLJ types can be queried just like ordinary SQL object types.

Methods called in a SELECT statement must not attempt to change attribute values.

Inserting Java Objects

Inserting a row in a table containing a column of a SQLJ type requires a call to the type's constructor function to create a Java object of that type.

The implicit, system-generated constructor can be used, or a static function can be defined that maps to a user-defined constructor in the Java class.

Updating SQLJ Objects

SQLJ objects can be updated either by using an UPDATE statement to modify the value of one or more attributes, or by invoking a method that updates the attributes and returns SELF--that is, returns the object itself with the changes made.

For example, suppose that raise() is a member function that increments the salary field/attribute by a specified amount and returns SELF. The following statement gives every employee in the object table employee_objtab a raise of 1000:

UPDATE employee_objtab SET c=c.raise(1000);

A column of a SQLJ type can be set to NULL or to another column using the same syntax as for ordinary object types. For example, the following statement assigns column d to column c:

UPDATE employee_reltab SET c=d ;

Defining User-Defined Constructors in Java

When you implement a user-defined constructor in Java, the string supplied as the implementing routine must correspond to a static function. For the return type of the function, specify the Java type mapped to the SQL type.

Here is an example of a type declaration that involves a user-defined constructor implemented in Java:

CREATE OR REPLACE TYPE Person1_typ AS OBJECT (
  name VARCHAR2(30), 
  age NUMBER
  CONSTRUCTOR FUNCTION Person1_typ(name VARCHAR2, age NUMBER)
    RETURN Person1_typ AS RESULT
  AS LANGUAGE JAVA 
    NAME 'pkg1.J_Person.J_Person(java.lang.String, int) return J_Person'
);


Go to previous page Go to next page
Oracle
Copyright © 1996, 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