Skip Headers

Oracle9i XML Database Developer's Guide - Oracle XML DB
Release 2 (9.2)

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

9
Java and Java Bean APIs for XMLType

This chapter describes how to use XMLType in Java, including fetching XMLType data through JDBC and manipulating them using the Java Bean API.

Introducing Java DOM and Java Bean APIs for XMLType

Oracle XML DB supports the following Java Application Program Interfaces (APIs):

Java DOM API for XMLType

Java DOM API for XMLType handles all kinds of valid XML documents irrespective of how they are stored in Oracle XML DB. It presents to the application a uniform view of the XML document irrespective of whether it is XML schema-based or non- schema-based, whatever the underlying storage. Java DOM API works on client and server.

As discussed in Chapter 8, "PL/SQL API for XMLType", the Oracle XML DB DOM APIs are compliant with W3C DOM Level 1.0 and Level 2.0 Core Recommendation.

Accessing XML Documents in Repository

Oracle XML DB Resource API for Java/JNDI API allows Java applications to access XML documents stored in the Oracle XML DB Repository. Naming conforms to the Java binding for DOM as specified by the W3C DOM Recommendation. Oracle XML DB Repository hierarchy can store both XML schema-based and non- schema-based documents.

See:

Chapter 17, "Oracle XML DB Resource API for Java/JNDI"

Accessing XML Documents Stored in Oracle9i Database (Java)

Oracle XML DB provides two ways (part of the Java/JNDI resource APIs) for Java applications to access XML data stored in a database:

How Java Applications Use JNDI to Access XML Documents in Oracle XML DB

JNDI allows navigational access to XML documents stored in Oracle XML DB Repository hierarchy. This is described in Chapter 17, "Oracle XML DB Resource API for Java/JNDI". Depending on the access type specified to JNDI, either a document object or a bean object is returned. The JNDI lookup() method obtains an XML object from Oracle XML DB Repository when given a path name, if the object is an XML schema-based document:

The Java application can also call the Java DOM API for XMLType for objects for which beans have been generated. This is because the Java Beans interface is based on an extension to the DOM. Once the application has the object returned by lookup(), it can call either the Java DOM API for XMLType methods or Java Beans methods on the class to access XML data. For Java DOM API for XMLType, an XMLDocument class, which implements the DOM interface, is returned.

For example:

Document x = (org.w3c.dom.Document)ctx.lookup("/usr/local/bkhaladk/po.xml"); 

How Java Applications Use JDBC to Access XML Documents in Oracle XML DB

JDBC users can query an XMLType table to obtain a JDBC XMLType interface that supports all methods supported by the SQL XMLType data type. The Java (JDBC) API for XMLType interface can implement the DOM document interface.

JavaBean support is not available through JDBC because JDBC can work on both client and server, and the Java Bean API for XMLType is designed to work only in the server.

Example 9-1 XMLType Java: Using JDBC to Query an XMLType Table

The following is an example that illustrates using JDBC to query an XMLType table:

import oracle.xdb.XMLType; 
            ... 
   OraclePreparedStatement stmt = (OraclePreparedStatement) 
conn.prepareStatement("select e.poDoc from po_xml_tab e"); 
       ResultSet rset = stmt.executeQuery(); 
       OracleResultSet orset = (OracleResultSet) rset; 

while(orset.next())
        { 
       // get the XMLType 
       XMLType poxml = XMLType.createXML(orset.getOPAQUE(1)); 
       // get the XMLDocument as a string... 
Document podoc = (Document)poxml.getDOM(); 
        }

Example 9-2 XMLType Java: Selecting XMLType Data

You can select the XMLType data in JDBC in one of two ways:

Example 9-3 XMLType Java: Directly Returning XMLType Data

This example shows the use of getObject to directly get the XMLType from the ResultSet. This is the easiest way to get the XMLType from the ResultSet.

import oracle.xdb.XMLType;
...

 OraclePreparedStatement stmt = 
    (OraclePreparedStatement) conn.prepareStatement(
          "select e.poDoc from po_xml_tab e");

ResultSet rset = stmt.executeQuery();
OracleResultSet orset = (OracleResultSet) rset;
while(orset.next())
        {

// get the XMLType
XMLType poxml = (XMLType)orset.getObject(1);

// get the XML as a string...
String poString = poxml.getStringVal();
        }

Using JDBC to Manipulate XML Documents Stored in a Database

You can also update, insert, and delete XMLType data using JDBC.

Example 9-4 XMLType Java: Updating/Inserting/Deleting XMLType Data

You can insert an XMLType in java in one of two ways:

Example 9-5 XMLType Java: Getting Metadata on XMLType

When selecting out XMLType values, JDBC describes the column as an OPAQUE type. You can select the column type name out and compare it with "XMLTYPE" to check if you are dealing with an XMLType:

import oracle.sql.*;
import oracle.jdbc.*;
...
OraclePreparedStatement stmt = 
    (OraclePreparedStatement) conn.prepareStatement(
        "select poDoc from po_xml_tab");

OracleResultSet rset = (OracleResultSet)stmt.exuecuteQuery();

// Now, we can get the resultset metadata
OracleResultSetMetaData mdata = 
        (OracleResultSetMetaData)rset.getMetaData();

// Describe the column = the column type comes out as OPAQUE
// and column type name comes out as XMLTYPE
if (mdata.getColumnType(1) == OracleTypes.OPAQUE && 
    mdata.getColumnTypeName(1).compareTo("SYS.XMLTYPE") == 0)
{
   // we know it is an XMLtype
}

Example 9-6 XMLType Java: Updating an Element in an XMLType Column

This example updates the discount element inside PurchaseOrder stored in an XMLType column. It uses Java (JDBC) and the oracle.xdb.XMLType class. This example also shows you how to insert/update/delete XMLTypes using Java (JDBC). It uses the parser to update an in-memory DOM tree and write the updated XML value to the column.

-- create po_xml_hist table to store old PurchaseOrders
create table po_xml_hist (
 xpo xmltype
);

/*
   DESCRIPTION
    Example for oracle.xdb.XMLType

   NOTES
   Have classes12.zip, xmlparserv2.jar, and oraxdb.jar in CLASSPATH

*/

import java.sql.*;
import java.io.*;

import oracle.xml.parser.v2.*;
import org.xml.sax.*;
import org.w3c.dom.*;

import oracle.jdbc.driver.*;
import oracle.sql.*;

import oracle.xdb.XMLType;

public class tkxmtpje
{

  static String conStr = "jdbc:oracle:oci8:@";
  static String user = "scott";
  static String pass = "tiger";
  static String qryStr = 
        "SELECT x.poDoc from po_xml_tab x "+
        "WHERE  x.poDoc.extract('/PO/PONO/text()').getNumberVal()=200";

 static String updateXML(String xmlTypeStr)
  {
     System.out.println("\n===============================");
     System.out.println("xmlType.getStringVal():");
     System.out.println(xmlTypeStr);
     System.out.println("===============================");
     String outXML = null;
     try{
        DOMParser parser  = new DOMParser();
        parser.setValidationMode(false);
        parser.setPreserveWhitespace (true);    

        parser.parse(new StringReader(xmlTypeStr));
        System.out.println("xmlType.getStringVal(): xml String is well-formed");

        XMLDocument doc = parser.getDocument();

        NodeList nl = doc.getElementsByTagName("DISCOUNT");

        for(int i=0;i<nl.getLength();i++){
           XMLElement discount = (XMLElement)nl.item(i);
           XMLNode textNode = (XMLNode)discount.getFirstChild();
           textNode.setNodeValue("10");
        }

       StringWriter sw = new StringWriter();
       doc.print(new PrintWriter(sw));

       outXML = sw.toString();

      //print modified xml
       System.out.println("\n===============================");
       System.out.println("Updated PurchaseOrder:");
       System.out.println(outXML);
       System.out.println("===============================");
      }
    catch ( Exception e )
    {
      e.printStackTrace(System.out);
    }
    return outXML;
  }

 public static void main(String args[]) throws Exception
  {
    try{

        System.out.println("qryStr="+ qryStr);

        DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());

        Connection conn = 
          DriverManager.getConnection("jdbc:oracle:oci8:@", user, pass);

        Statement s = conn.createStatement();
        OraclePreparedStatement stmt;

        ResultSet rset = s.executeQuery(qryStr);
        OracleResultSet orset = (OracleResultSet) rset;

        while(orset.next()){

        //retrieve PurchaseOrder xml document from database
         XMLType xt = XMLType.createXML(orset.getOPAQUE(1));
         
         //store this PurchaseOrder in po_xml_hist table
         stmt = (OraclePreparedStatement)conn.prepareStatement(
                   "insert into po_xml_hist values(?)");

         stmt.setObject(1,xt);  // bind the XMLType instance
         stmt.execute();

         //update "DISCOUNT" element
         String newXML = updateXML(xt.getStringVal());

         // create a new instance of an XMLtype from the updated value
         xt = XMLType.createXML(conn,newXML);

        // update PurchaseOrder xml document in database
         stmt = (OraclePreparedStatement)conn.prepareStatement(
           "update po_xml_tab x set x.poDoc =? where "+
             "x.poDoc.extract('/PO/PONO/text()').getNumberVal()=200");

         stmt.setObject(1,xt);  // bind the XMLType instance
         stmt.execute();

         conn.commit();
         System.out.println("PurchaseOrder 200 Updated!");

        }

       //delete PurchaseOrder 1001
        s.execute("delete from po_xml x"+
           "where x.xpo.extract"+
              "('/PurchaseOrder/PONO/text()').getNumberVal()=1001");
        System.out.println("PurchaseOrder 1001 deleted!");
    }
    catch( Exception e )
    {
      e.printStackTrace(System.out);
    }
  }
}

---------------------- 
-- list PurchaseOrders
----------------------

set long 20000
set pages 100
select x.xpo.getClobVal()
from po_xml x;

Here is the resulting updated purchase order in XML:

<?xml version = '1.0'?>
<PurchaseOrder>
  <PONO>200</PONO>
  <CUSTOMER>
   <CUSTNO>2</CUSTNO>
   <CUSTNAME>John Nike</CUSTNAME>
   <ADDRESS>
    <STREET>323 College Drive</STREET>
    <CITY>Edison</CITY>
    <STATE>NJ</STATE>
    <ZIP>08820</ZIP>
   </ADDRESS>
   <PHONELIST>
    <VARCHAR2>609-555-1212</VARCHAR2>
    <VARCHAR2>201-555-1212</VARCHAR2>
   </PHONELIST>
  </CUSTOMER>
  <ORDERDATE>20-APR-97</ORDERDATE>
  <SHIPDATE>20-MAY-97 12.00.00.000000 AM</SHIPDATE>
  <LINEITEMS>
   <LINEITEM_TYP LineItemNo="1">
    <ITEM StockNo="1004">
     <PRICE>6750</PRICE>
     <TAXRATE>2</TAXRATE>
    </ITEM>
    <QUANTITY>1</QUANTITY>
    <DISCOUNT>10</DISCOUNT>
   </LINEITEM_TYP>
   <LINEITEM_TYP LineItemNo="2">
    <ITEM StockNo="1011">
     <PRICE>4500.23</PRICE>
     <TAXRATE>2</TAXRATE>
    </ITEM>
    <QUANTITY>2</QUANTITY>
    <DISCOUNT>10</DISCOUNT>
   </LINEITEM_TYP>
  </LINEITEMS>
  <SHIPTOADDR>
   <STREET>55 Madison Ave</STREET>
   <CITY>Madison</CITY>
   <STATE>WI</STATE>
   <ZIP>53715</ZIP>
  </SHIPTOADDR>
</PurchaseOrder>

Example 9-7 Manipulating an XMLType Column

This example performs the following:

Java DOM API for XMLType Features

When you use the JNDI API to get XML data from Oracle XML DB, you get an XMLDocument object that represents the XML data or file you retrieve. The XMLDocument object returned by JNDI implements the DOM interface. From this document interface you can get the elements of the document and perform all the operations specified in the W3C DOM specification. The DOM works on:

The Java DOM API for XMLType supports deep or shallow searching in the document to retrieve children and properties of XML objects such as name, namespace, and so on. Conforming to the DOM 2.0 recommendation, Java DOM API for XMLType is namespace aware.

Creating XML Documents Programmatically

Java API for XMLType also allows applications to create XML documents programmatically. This way applications can create XML documents on the fly (or dynamically) that either conform to a preregistered XML schema or are non-XML schema-based documents.

Creating XML Schema-Based Documents

To create XML schema-based documents, Java DOM API for XMLType uses an extension to specify which XML schema URL to use. For XML schema-based documents, it also verifies that the DOM being created conforms to the specified XML schema, that is, that the appropriate children are being inserted under the appropriate documents.


Note:

In this release, Java DOM API for XMLType does not perform type and constraint checks.


Once the DOM object has been created, it can be saved to Oracle XML DB Repository using the Oracle XML DB Resource API for Java's JNDI API bind(). The XML document is stored in the appropriate format:

Example 9-8 Java DOM API for XMLType: Creating a DOM Object and Storing It in the Format Specified by the XML Schema

The following example shows how you can use Java DOM API for XMLType to create a DOM object and store it in the format specified by the XML schema. Note that the validation against the XML schema is not shown here.

import oracle.xdb.XMLType;
...
OraclePreparedStatement stmt = 
    (OraclePreparedStatement) conn.prepareStatement(
        "update po_xml_tab set poDoc = ? ");

// the second argument is a string
String poString = "<PO><PONO>200</PONO><PNAME>PO_2</PNAME></PO>";
XMLType poXML = XMLType.createXML(conn, poString);
Document poDOM = (Document)poXML.getDOM();

Element rootElem = poDOM.createElement("PO");
poDOM.insertBefore(poDOM, rootElem, null);

// now bind the string..
stmt.setObject(1,poXML);
stmt.execute();

JDBC/SQLJ

An XMLType instance is represented in Java by oracle.xdb.XMLType. When an instance of XMLType is fetched using JDBC, it is automatically manifested as an object of the provided XMLType class. Similarly, objects of this class can be bound as values to Data Manipulation Language (DML) statements where an XMLType is expected. The same behavior is supported in SQLJ clients.

Java DOM API for XMLType Classes

Oracle XML DB supports the W3C DOM Level 2 recommendation.

In addition to the W3C recommendation, Oracle XML DB DOM API also provides Oracle-specific extensions, mainly to facilitate your application interfacing with Oracle XDK for Java. A list of the Oracle extensions is found at: http://otn.oracle.com/docs/tech/xml/xdk_java/content.html


XMLDocument() is a class that represents the DOM for the instantiated XML document. You can retrieve the XMLType from the XML document using the function getXMLType() on XMLDocument() class.

Table 9-1 lists the Java DOM API for XMLType classes and the W3C DOM interfaces they implement.

Table 9-1 Java DOM API for XMLType: Classes  
Java DOM API for XMLType Class W3C DOM Interface Recommendation Class

oracle.xdb.dom.XMLDocument

org.w3c.dom.Document

oracle.xdb.dom.XMLCData

org.w3c.dom.CDataSection

oracle.xdb.dom.XMLComment

org.w3c.dom.Comment

oracle.xdb.dom.XMLPI

org.w3c.dom.ProcessingInstruction

oracle.xdb.dom.XMLText

org.w3c.dom.Text

oracle.xdb.dom.XMLEntity

org.w3c.dom.Entity

oracle.xdb.dom.DTD

org.w3c.dom.DocumentType

oracle.xdb.dom.XMLNotation

org.w3c.dom.Notation

oracle.xdb.dom.XMLNodeList

org.w3c.dom.NodeList

oracle.xdb.dom.XMLAttribute

org.w3c.dom.Attribute

oracle.xdb.dom.XMLDOMImplementation

org.w3c.dom.DOMImplementation

oracle.xdb.dom.XMLElement

org.w3c.dom.Element

oracle.xdb.dom.XMLNamedNodeMap

org.w3c.dom.NamedNodeMap

oracle.xdb.dom.XMLNode

org.w3c.dom.Node

Java DOM API for XMLType: Calling Sequence

The following Java DOM API for XMLType calling sequence description assumes that your XML data is pre-registered with an XML schema and that it is stored in an XMLType datatype column. To use the Java DOM API for XMLType, follow these steps:

  1. Retrieve the XML data from the XMLType table or XMLType column in the table. When you fetch XML data, Oracle XML DB creates a DOMDocument instance of XMLType, parsing the document into a DOM tree. You can then manipulate elements in the DOM tree using Java DOM API for XMLType.
  2. Use the Java DOM API for XMLType to perform operations and manipulations on elements of the DOM tree.
  3. The Java DOM API for XMLType sends the changed XML data back to Oracle XML DB.

Figure 9-1 illustrates the Java DOM API for XMLType calling sequence.

Figure 9-1 Java DOM API for XMLType: Calling Sequence

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


Java Bean API for XMLType

The Java Bean API for XMLType is a specialized API for working with XML schema-based data. The XML schema must be registered with Oracle XML DB. Java Bean API for XMLType is optimized for processing XML data by Java applications in the server.

See Also:

Chapter 5, "Structured Mapping of XMLType" for details on registering XML schema

Use the Java Bean API for XMLType for applications that:

The Java bean source file is stored in your home directory in Oracle XML DB Repository under the bean/ directory. You can use this source file for the list of beans generated for the specific XML schema.

Java Beans Names Are Always Unique

The rule described here is used for XML schema generation. The package name, oracle.xdb.bean, is prepended to the name of the XML schema.

The bean name is always unique and is generated as the XML schema name, appended with its number in the XML schema file. For example, if a file, emp.xsd, contains three schemas: Emp, Def, and Manager, then:

Thus, class Emp() will be unique in package Emp1. This way Java bean names are always unique.

Use registerSchema() to Register Your XML Schema and Generate Java Beans

Java beans are generated when the XML schema is registered with Oracle XML DB using registerSchema() with genbean flag set to TRUE.


Note:

You can also generate Java Beans independently using the generateBean() function in DBMS_XMLSCHEMA package. This can be done as many times as you wish.

The deleteSchema() PLSQL call removes the Java bean class files from Oracle XML DB. See Chapter 5, "Structured Mapping of XMLType".


Guidelines for Using Java Bean API for XMLType

The following are guidelines for using Java Bean API for XMLType:

  1. First register the XML schema with Oracle XML DB. The XML Schema registration API has a flag that enables the caller to generate a bean for the XML schema. The flag is optional since not all XML schema users use Java Bean API for XMLType.

    See Also:

    Chapter 5, "Structured Mapping of XMLType".

    The Java bean generation process generates the Java bean code and compiles it into the server where your XML schema resides. A copy of the source file is also placed in the Oracle XML DB Repository hierarchy in your home directory. This is needed for you to later compile your source code.

  2. The Java bean classes are generated in a package with the name of the XML schema file. Different XML schema types are mapped to Java types based on rules specified in the XML schema. See Table 9-3, "Mapping Between XML Schema, SQL, and Java DataTypes". For example:
    • Oracle XML DB for Java Bean API uses the reflection mechanism to generate class names. For all attributes and children there will be get and set methods in the API. These get and set methods will be suffixed with the name of the child.
    • For server side applications, Java Bean API for XMLType objects are accessed using JNDI lookup() API. In this case the XDB_ACCESS_TYPE flag specifies BEAN as the access type.
  3. Java Bean API for XMLType can also be used for creating new schema-based XML documents. The applications can instantiate bean classes and use the set methods to set the appropriate data in the document. Similar to DOM, the JNDI bind() method is Java bean aware and can be used to save the XML schema document in Oracle XML DB Repository. See also Chapter 17, "Oracle XML DB Resource API for Java/JNDI".

Figure 9-2 illustrates the Java Bean API for XMLType calling sequence.

Figure 9-2 Java Bean API for XMLType: Calling Sequence

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


Table 9-2 describes the mapping of XML schema entities to the Java bean classes/methods.

Table 9-2 JavaBeans API for XMLType: Mapping of XML Schema Entities
XML Schema Entity JavaBeans Classes/Methods Description

Attribute

get/setAttribute{attrname}

Complextype

get/set{complextype classname}.

For complex children separate bean classes get generated. Extras (processing instructions/comments). DOM classes for processing-instruction/comments are returned.

Scalar data

get/set{scalar type name}

Children with maxoccurs > 1 Get/set List of type of child

Table 9-3 describes the mapping used by Java Bean API For XMLType between XML schema, SQL, and Java datatypes.

Table 9-3 Mapping Between XML Schema, SQL, and Java DataTypes  
XML Schema Data Type SQL DataType Java Data Type

Boolean

boolean

boolean

String

URI reference

ID

IDREF

ENTITY

NOTATION

Language

NCName

Name

java.lang.String

String

DECIMAL

INTEGER

LONG

SHORT

INT

POSITIVEINTEGER

NONPOSITIVEINTEGER

oracle.sql.Number

int

FLOAT

DOUBLE

oracle.sql.Number

float

TIMEDURATION

TIMEPERIOD

RECURRINGDURATION

DATE

TIME

MONTH,YEAR

RECURRINGDATE

java.sql.Timestamp

Time

REF

oracle.sql.Ref

Ref

BINARY

oracle.sql.RAW

Byte[]

QNAME

java.lang.String

String

Example 9-9 Java Bean API for XMLType

This example illustrates the use of Java Bean API for XMLType. Assume the following XML schema:

<schema targetNamespace="http://www.oracle.com/tkxmsch1.xsd" version="1.0"> 
<element name = "Employee"> 
<complexType> 
<sequence> 
<element name = "EmployeeId" type = "positiveInteger"/> 
<element name = "FirstName" type = "string"/> 
<element name = "LastName" type = "string"/> 
<element name = "Salary" type = "positiveInteger"/> 
</sequence> 
</complexType> 
</element> 
</schema> 

The generated Java bean for this XML schema looks like this:

/* bean file generated by Oracle XML DB */ 
package oracle.xdb.bean.tkxmsch1; 
import org.w3c.dom.*; 
import oracle.xdb.dom.*; 
import oracle.xdb.bean.*; 
import java.util.Vector; 

public class Employee extends XMLTypeBean 
{ 
public Employee(XMLType owner, long xob, long kidnum) 
{ 
super(owner, xob, kidnum); 
} 

public Employee() 
{ 
super(null, 0, 0); 
} 

public int getEmployeeId() 
{ 
return super.getScalarint(0); 
} 

public void setEmployeeId(int val) 
{ 
super.setScalar(0, val); 
return; 
} 

public String getFirstName() 
{ 
return super.getScalarString(1); 
} 

public void setFirstName(String val) 
{ 
super.setScalar(1, val); 
return; 
} 

public String getLastName()
{
return super.getScalarString(2);
}

public void setLastName(String val)
{ 
super.setScalar(2, val);
return;
}

public int getSalary() 
{ 
return super.getScalarint(3); 
} 

public void setSalary(int val)
{
super.setScalar(3, val);
return;
}
}

Here is the Java Stored Procedure:

Hashtable env = new Hashtable();
env.put(Context.PROVIDER_URL, "/");
env.put(Context.INITIAL_CONTEXT_FACTORY,"oracle.xdb.spi.XDBContextFactory");
Context ctx = (Context)new InitialContext(env); 
Employee obj = (Employee)ctx.lookup("/tkxms1d1.xml");
return obj.getFirstName();

See Also:

Oracle9i XML API Reference - XDK and Oracle XML DB


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