ヘッダーをスキップ
Oracle® XML DB開発者ガイド
11gリリース2 (11.2)
B70200-03
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

15 Java DOM API for XMLType

この章では、Java Database Connectivity(JDBC)を介したXMLTypeデータのフェッチなど、JavaでXMLTypeを使用する方法を説明します。

この章の内容は次のとおりです。

Java DOM API for XMLTypeの概要

Oracle XML DBはJava Document Object Model (DOM) Application Program Interface (API) for XMLTypeをサポートします。これはXML Schemaに基づく文書とXML Schemaに基づかない文書に対する、クライアントおよびサーバー用の汎用APIです。このAPIは、Javaパッケージoracle.xml.parser.v2を使用して実装されます。DOMは、XML文書のメモリー内ツリーベースのオブジェクト表現で、要素および属性へのプログラム・アクセスを可能にします。DOMオブジェクトおよびインタフェースは、W3C勧告の一部です。DOMは、解析対象ドキュメントをオブジェクトのツリーとして表示します。

JDBCを使用してXMLTypeデータにアクセスするには、クラスoracle.xdb.XMLTypeを使用します。

どのXML Schemaにも準拠しないXML文書には、すべての妥当なXML文書を処理可能なJava DOM API for XMLTypeを使用できます。


関連項目:

『Oracle Database XML Java API Reference』

Java DOM API for XMLType

Java DOM API for XMLTypeは、Oracle XML DBへの格納方法にかかわらず、すべての種類の妥当なXML文書を処理します。XML文書は、XML Schemaに基づくか、XML Schemaに基づかないか(基礎となる記憶域モデルの形式が何であるか)にかかわらず、アプリケーションで同様に表示されます。Java DOM APIは、クライアントおよびサーバーの両方で動作します。

第13章「PL/SQL API for XMLType」で説明したとおり、Oracle XML DB DOM APIは、W3CのDOMレベル1.0およびレベル2.0のコア勧告に準拠しています。

Java DOM API for XMLTypeを使用すると、別のキャラクタ・セットでエンコードされたデータからXMLTypeインスタンスを作成できます。

Java DOM API for XMLTypeを使用して、JavaアプリケーションからOracle XML DBリポジトリに格納されたXML文書にアクセスできます。ネーミングは、W3CのDOM勧告で指定されている、DOMへのJavaバインディングに準拠しています。リポジトリには、XML Schemaに基づくドキュメントおよび基づかないドキュメントの両方を含めることができます。

JDBCを使用したXMLTypeデータへのアクセス

JDBCは、Oracle XML DB内のXML文書など、Oracle Database内のすべてのデータにアクセスするための、Javaアプリケーション用のSQLベースの方法です。XMLデータを作成するには、oracle.xdb.XMLType JavaクラスのcreateXML()メソッドを使用します。


注意:

入力としてストリームを引き渡す場合は、メソッドXMLType.createXML()とThickドライバを使用してください。この場合、Thinドライバは使用できません。

JDBCとのXMLTypeデータの使用

XMLデータのJDBC 4.0標準データ型はjava.sql.SQLXMLです。getObject()メソッドでは、oracle.xdb.XMLType型のオブジェクトが戻されます。Oracle Databaseリリース2 (11.2.0.3)から、oracle.xdb.XMLTypeがインタフェースjava.sql.SQLXMLを実装しています。

JDBCを使用してJavaアプリケーションでOracle XML DB内のXML文書にアクセスする方法

JDBCユーザーは、XMLType表を問い合せて、SQL XMLTypeデータ型でサポートされるすべてのSQL/XML関数をサポートするJDBC XMLTypeインタフェースを取得できます。Java(JDBC)API for XMLTypeインタフェースは、DOMDocumentインタフェースを実装できます。

例15-1に、JDBCを使用してXMLType表を問い合せる方法を示します。

例15-1 JDBCを使用したXMLType表の問合せ

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 XMLDocument as a string... 
  Document podoc = (Document)poxml.getDOM(); 
  }

次のいずれかの方法で、JDBCを使用してXMLTypeデータを選択できます。

  • SQLでSQL/XML関数XMLSerializeを使用し、Javaでoracle.sql.CLOBjava.lang.Stringまたはoracle.sql.BLOBとして結果を取得します。例15-2のJavaスニペットに、これを示します。

  • PreparedStatementでメソッドgetObject()をコールして、XMLTypeインスタンス全体を取得します。このメソッドの戻り値は、oracle.xdb.XMLType型です。これによって、XMLTypeクラスでJava関数を使用して、データにアクセスできます。この方法を例15-3に示します。

例15-2 getStringVal()およびgetCLOB()を使用したXMLTypeデータの選択

DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Connection conn = 
  DriverManager.getConnection("jdbc:oracle:oci8:@", "QUINE", "CURRY");
OraclePreparedStatement stmt = 
  (OraclePreparedStatement) conn.prepareStatement(
     "SELECT XMLSerialize(DOCUMENT e.poDoc AS CLOB) poDoc, " +
     "XMLSerialize(DOCUMENT e.poDoc AS VARCHAR2(2000)) poString " +
     " FROM po_xml_tab e");
ResultSet rset = stmt.executeQuery();
OracleResultSet orset = (OracleResultSet) rset;
while(orset.next())
  {
  // the first argument is a CLOB
  oracle.sql.CLOB clb = orset.getCLOB(1);
  // the second argument is a string..
  String poString = orset.getString(2);
  // now use the CLOB inside the program
  }

例15-3では、getObject()メソッドを使用してResultSetからXMLTypeインスタンスを直接取得します。

例15-3 getObject()を使用してXMLTypeデータを戻す方法

import oracle.xdb.XMLType;
...
PreparedStatement stmt =  conn.prepareStatement(
  "SELECT e.poDoc FROM po_xml_tab e"); 
ResultSet rset = stmt.executeQuery(); 
while(rset.next())
{ 
// get the XMLType 
XMLType poxml = (XMLType)rset.getObject(1); 
// get the XML as a string...
String poString = poxml.getStringVal();
}

例15-4では、XMLType型の出力パラメータをSQL文にバインドします。この出力パラメータは、XMLTypeデータ型として登録されます。

例15-4 出力パラメータを使用してXMLTypeデータを戻す方法

public void doCall (String[] args) 
  throws Exception 
  { 
//  CREATE OR REPLACE FUNCTION getPurchaseOrder(reference VARCHAR2) 
//  RETURN XMLTYPE 
//  AS 
//    xml XMLTYPE; 
//  BEGIN 
//    SELECT OBJECT_VALUE INTO xml 
//      FROM purchaseorder 
//      WHERE XMLCast(XMLQuery('$p/PurchaseOrder/Reference'
//                             PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
//                    AS VARCHAR2(30))
//            = reference;
//      RETURN xml; 
//  END; 
    String SQLTEXT = "{? = call getPurchaseOrder('BLAKE-2002100912333601PDT')}"; 
    CallableStatement sqlStatement = null; 
    XMLType xml = null; 
    super.doSomething(args); 
    createConnection(); 
    try 
    { 
      System.out.println("SQL := " + SQLTEXT); 
      sqlStatement = getConnection().prepareCall(SQLTEXT); 
      sqlStatement.registerOutParameter (1, OracleTypes.OPAQUE,"SYS.XMLTYPE"); 
      sqlStatement.execute(); 
      xml = (XMLType) sqlStatement.getObject(1); 
      System.out.println(xml.getStringVal()); 
    } 
    catch (SQLException SQLe) 
    { 
      if (sqlStatement != null) 
      { 
        sqlStatement.close(); 
        throw SQLe; 
      } 
    } 

JDBCを使用したXMLデータベース文書の操作

Java Database Connectivity(JDBC)を使用して、XMLTypeデータを更新、挿入および削除することもできます。


注意:

XMLTypeメソッドのextract()transform()およびexistsNode()は、OCIドライバでのみ機能します。

Thin JDBCドライバでは、すべてのoracle.xdb.XMLType関数がサポートされているわけではありません。oracle.xdb.XMLTypeクラスとOCIドライバを使用しない場合、XMLのインテリジェント処理に関連したパフォーマンスのメリットを失う可能性があります。


XMLTypeデータを次のいずれかの方法で、更新、挿入または削除できます。

  • CLOBまたは文字列をINSERTUPDATEまたはDELETE文にバインドし、SQL内でXMLTypeコンストラクタを使用してXMLインスタンスを作成します。例15-5に、これを示します。

  • PreparedStatementsetObject()を使用して、XMLTypeインスタンス全体を設定します。例15-6に、これを示します。

例15-5 SQL UPDATEとコンストラクタXMLTypeを使用したXMLTypeデータの更新

OraclePreparedStatement stmt = 
    (OraclePreparedStatement) conn.prepareStatement(
        "UPDATE po_xml_tab SET poDoc = XMLType(?)");

// the second argument is a string..
String poString = "<PO><PONO>200</PONO><PNAME>PO_2</PNAME></PO>";

// now bind the string..
stmt.setString(1,poString);
stmt.execute();

例15-6 SQL UPDATEとsetObject()を使用したXMLTypeデータの更新

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);

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

XMLType値を選択すると、JDBCによって、列が不透明型として記述されます。列型の名前を選択し、それをXMLTYPEと比較すると、XMLTypeインスタンスを処理しているかどうかを確認できます。例15-7に、これを示します。

例15-7 JDBCを使用したXMLTypeデータに関するメタデータの取得

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

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

// 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)
{
   // It is an XMLtype
}

例15-8では、XMLType列に格納されているPurchaseOrder要素内のdiscount要素を更新します。ここではJDBCおよびoracle.xdb.XMLTypeクラスを使用します。XMLパーサーを使用してDOMツリーを更新し、更新されたXML値をXMLType列に書き込みます。

例15-8 JDBCを使用したXMLType列の要素の更新

-- Create po_xml_hist table to store old PurchaseOrders
CREATE TABLE po_xml_hist (xpo XMLType);
/* NOTE: You must have xmlparserv2.jar and xdb.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 = "QUINE";
  static String pass = "CURRY";
  static String qryStr =
  "SELECT x.poDoc from po_xml_tab x " +
  "WHERE XMLCast(XMLQuery('/PO/PONO/text()'" +
  " PASSING x.poDoc RETURNING CONTENT)" +
  " AS NUMBER)" +
  " = 200";
  static String updateXML(String xmlTypeStr)
  Java DOM API for XMLType
  Beta Draft Java DOM API for XMLType 15-7
    {
    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)orset.getObject(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 " +
        "XMLCast(XMLQuery('/PO/PONO/text()'" +
        " PASSING value(xmltab) RETURNING CONTENT)" +
        " AS NUMBER)" +
        "= 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" +
                "XMLCast(XMLQuery('/PurchaseOrder/PONO/text()'" +
                " PASSING value(xmltab) RETURNING CONTENT)" +
                " AS NUMBER)" +
                "= 1001");
      System.out.println("PurchaseOrder 1001 deleted!");
      }
  catch(Exception e)
    {
    e.printStackTrace(System.out);
    }
  }
 
SELECT x.xpo.getCLOBVal() FROM po_xml x;

例15-9は、例15-8から得られる更新済の発注書を示します。

例15-9 更新済の発注書

<?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>

例15-10では、次のものがすべて処理されます。

  • XMLType表からのXMLTypeインスタンスの選択

  • XPath式に基づくXMLTypeインスタンスの一部の抽出

  • 要素の有無の確認

  • XSLに基づく別のXML形式へのXMLTypeインスタンスの変換

  • XML Schemaに対するXMLType文書の妥当性の確認

例15-10 JDBCを使用したXMLType列の操作

import java.sql.*;
import java.io.*;
import java.net.*;
import java.util.*;
import oracle.xml.parser.v2.*;
import oracle.xml.parser.schema.*;
import org.xml.sax.*;
import org.w3c.dom.*;
import oracle.xml.sql.dataset.*;
import oracle.xml.sql.query.*;
import oracle.xml.sql.docgen.*;
import oracle.xml.sql.*;
import oracle.jdbc.driver.*;
import oracle.sql.*;
import oracle.xdb.XMLType;
public class tkxmtpk1
{
static String conStr = "jdbc:oracle:oci8:@";
static String user = "tpjc";
static String pass = "tpjc";
static String qryStr = "select x.resume from t1 x where id<3";
static String xslStr =
"<?xml version='1.0'?> " +
"<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1" +
"999/XSL/Transform'> " +
"<xsl:template match='ROOT'> " +
"<xsl:apply-templates/> " +
"</xsl:template> " +
"<xsl:template match='NAME'> " +
"<html> " +
" <body> " +
" This is Test " +
" </body> " +
"</html> " +
"</xsl:template> " +
"</xsl:stylesheet>";
static void parseArg(String args[])
{
conStr = (args.length >= 1 ? args[0]:conStr);
user = (args.length >= 2 ? args[1].substring(0, args[1].indexOf("/")):user);
pass = (args.length >= 2 ? args[1].substring(args[1].indexOf("/")+1):pass);
qryStr = (args.length >= 3 ? args[2]:qryStr);
}
/**
* Print the byte array contents
*/
static void showValue(byte[] bytes) throws SQLException
{
if (bytes == null)
System.out.println("null");
else if (bytes.length == 0)
System.out.println("empty");
else
{
for(int i=0; i<bytes.length; i++)
System.out.print((bytes[i]&0xff)+" ");
System.out.println();
}
}
public static void main(String args[]) throws Exception
{
tkxmjnd1 util = new tkxmjnd1();
try{
if(args != null)
parseArg(args);
// System.out.println("conStr=" + conStr);
System.out.println("user/pass=" + user + "/" +pass );
System.out.println("qryStr=" + qryStr);
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection(conStr, user, pass);
Statement s = conn.createStatement();
ResultSet rset = s.executeQuery(qryStr);
OracleResultSet orset = (OracleResultSet) rset;
OPAQUE xml;
while(orset.next()){
oracle.xdb.XMLType xt = (oracle.xdb.XMLType)(orset.getObject(1));
System.out.println("Testing getDOM() ...");
Document doc = xt.getDOM();
util.printDocument(doc);
System.out.println("Testing getBytesValue() ...");
showValue(xt.getBytesValue());
System.out.println("Testing existsNode() ...");
try {
System.out.println("existsNode(/)" + xt.existsNode("/", null));
}
Java DOM API for XMLType
Beta Draft Java DOM API for XMLType 15-11
catch (SQLException e) {
System.out.println("Thin driver Expected exception: " + e);
}
System.out.println("Testing extract() ...");
try {
XMLType xt1 = xt.extract("/RESUME", null);
System.out.println("extract RESUME: " + xt1.getStringVal());
System.out.println("should be Fragment: " + xt1.isFragment());
}
catch (SQLException e) {
System.out.println("Thin driver Expected exception: " + e);
}
System.out.println("Testing isFragment() ...");
try {
System.out.println("isFragment = " + xt.isFragment()); }
catch (SQLException e)
{
System.out.println("Thin driver Expected exception: " + e);
}
System.out.println("Testing isSchemaValid() ...");
try {
System.out.println("isSchemaValid(): " + xt.isSchemaValid(null,"RES UME"));
}
catch (SQLException e) {
System.out.println("Thin driver Expected exception: " + e);
}
System.out.println("Testing transform() ...");
System.out.println("XSLDOC: \n" + xslStr + "\n");
try {
/* XMLType xslDoc = XMLType.createXML(conn, xslStr);
System.out.println("XSLDOC Generated");
System.out.println("After transformation:\n" + (xt.transform(xslDoc,
null)).getStringVal()); */
System.out.println("After transformation:\n" + (xt.transform(null,
null)).getStringVal());
}
catch (SQLException e) {
System.out.println("Thin driver Expected exception: " + e);
}
System.out.println("Testing createXML(conn, doc) ...");
try {
XMLType xt1 = XMLType.createXML(conn, doc);
System.out.println(xt1.getStringVal());
}
catch (SQLException e) {
System.out.println("Got exception: " + e);
}
}
}
catch(Exception e)
{
e.printStackTrace(System.out);
}
}
}

JDBCを使用した、データベースへの大規模なXML文書のロード

大規模なXML文書(通常4000文字を超える場合)がJDBCのStringオブジェクトを使用してXMLTypeの表または列に挿入されると、次のランタイム・エラーが発生します。

"java.sql.SQLException: Data size bigger than max size for this type"

このエラーは、JavaのCLOBオブジェクトを使用して大規模なXML文書を保持することで回避できます。例15-11に、このテクニックを使用するコードを示します。これはXMLTypeメソッドのinsertXML()を定義します。これを使用して、大規模なXML文書が表poTableXMLTypeの列purchaseOrderに挿入されます。XMLType表の場合も同じ方法を使用できます。

メソッドinsertXML()はXML文書を含むCLOBオブジェクトを使用します。CLOBオブジェクトは、クライアント側でクラスoracle.sql.CLOBを使用して作成されます。このクラスは、Oracle JDBC Driverによる標準JDBCインタフェースjava.sql.Clobの実装です。メソッドinsertXML()CLOBオブジェクトをJDBCのプリコンパイルされたSQL文にバインドします。これによりデータがXMLType列に挿入されます。

insertXML()を使用するための前提条件は、次のとおりです。

  • Oracle Databaseがリリース9.2.0.1以上であること。

  • ターゲット・データベース表が存在すること。例を実行する前に、次のSQLを実行してください。

    CREATE TABLE poTable (purchaseOrder XMLType);

XMLTypeメソッドのinsertXML()の仮パラメータは、次のとおりです。

  • xmlData: XMLType列に挿入するXMLデータ

  • conn: データベース接続オブジェクト(Oracle Connection Object)

例15-11 JavaメソッドinsertXML()

...
import oracle.sql.CLOB; 
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.PreparedStatement;
... 
 
private void insertXML(String xmlData, Connection conn) {
  CLOB clob = null;
  String query;
    // Initialize statement Object
  PreparedStatement pstmt = null;
  try{
    query = "INSERT INTO potable (purchaseOrder) VALUES (XMLType(?)) ";
    // Get the statement Object
    pstmt = conn.prepareStatement(query);
    // xmlData is the string that contains the XML Data.
    // Get the CLOB object.
    clob = getCLOB(xmlData, conn);
    // Bind this CLOB with the prepared Statement
    pstmt.setObject(1, clob);
    // Execute the Prepared Statement
    if (pstmt.executeUpdate () == 1) {
    System.out.println ("Successfully inserted a Purchase Order");
    }
  } catch(SQLException sqlexp){
    sqlexp.printStackTrace();
  } catch(Exception exp){
    exp.printStackTrace();
  }
}

JavaメソッドinsertXML()は、メソッドgetCLOB()をコールして、XMLデータを格納するCLOBオブジェクトを作成して戻します。getCLOB()メソッドの仮パラメータは例15-12で定義され、次のとおりです。

  • xmlData: XMLType列に挿入するXMLデータ

  • conn: データベース接続オブジェクト(Oracle Connection Object)

例15-12 JavaメソッドgetCLOB()

...
import oracle.sql.CLOB; 
import java.sql.Connection;
import java.sql.SQLException;
import java.io.Writer;
... 
 
private CLOB getCLOB(String xmlData, Connection conn) throws SQLException{
  CLOB tempClob = null;
  try{
    // If the temporary CLOB has not yet been created, create one
    tempClob = CLOB.createTemporary(conn, true, CLOB.DURATION_SESSION); 
 
    // Open the temporary CLOB in readwrite mode, to enable writing
    tempClob.open(CLOB.MODE_READWRITE); 
    // Get the output stream to write
    Writer tempClobWriter = tempClob.getCharacterOutputStream(); 
    // Write the data into the temporary CLOB
    tempClobWriter.write(xmlData); 
 
    // Flush and close the stream
    tempClobWriter.flush();
    tempClobWriter.close(); 
 
    // Close the temporary CLOB 
    tempClob.close();    
  } catch(SQLException sqlexp){
    tempClob.freeTemporary(); 
    sqlexp.printStackTrace();
  } catch(Exception exp){
    tempClob.freeTemporary(); 
    exp.printStackTrace();
  }
  return tempClob; 
}

関連項目:

『Oracle Database SecureFilesおよびラージ・オブジェクト開発者ガイド』

Java DOM API for XMLTypeの機能

Java DOM APIを使用してOracle XML DBからXMLデータを取得する場合:

  • 接続がThinの場合は、XMLDocumentインスタンスを取得します。

  • 接続がThickまたはkprbの場合は、getDOM()メソッドでXDBDocumentインスタンスを、getDocument()メソッドでXMLDocumentインスタンスを取得します。getDOM()メソッドとXDBDocumentクラスは非推奨になりました。

XMLDocumentおよびXDBDocument(非推奨)は、どちらもW3Cドキュメント・オブジェクト・モデル(DOM)・インタフェースのインスタンスです。このドキュメント・インタフェースからドキュメントの要素にアクセスすると、W3CのDOM勧告に指定されたすべての操作を実行できます。DOMは、次のものに対して機能します。

  • XML Schemaに基づく、基づかないに関係なく、あらゆる種類のXML文書

  • 文書で使用されるすべての形式の基礎となる記憶域

    • キャラクタ・ラージ・オブジェクト(Character Large Object: CLOB)

    • バイナリ・ラージ・オブジェクト(Binary Large Object: BLOB)

    • オブジェクト・リレーショナル

Java DOM API for XMLTypeは、XMLオブジェクトの子およびプロパティ(名前、名前空間など)を取得するために、文書内でのディープ検索およびシャロウ検索をサポートします。Java DOM API for XMLTypeはDOM 2.0勧告に準拠し、名前空間を認識します。

Java API for XMLTypeを使用すると、アプリケーションではプログラムによって、その場で(動的に)XML文書を作成できます。そのような文書は、登録されたXML Schemaに準拠することもあれば、しないこともあります。

XML Schemaに基づく文書の作成

XML Schemaに基づく文書を作成するには、Java DOM API for XMLTypeの拡張機能を使用して、使用するXML Schema URLを指定します。XML Schemaに基づく文書では、作成中のDOMが指定されたXML Schemaに準拠するかどうか(適切な子が適切な文書に挿入されているか)を検証します。


注意:

Java DOM API for XMLTypeは型および制約のチェックは実行しません

DOMオブジェクトの作成後は、Oracle XML DB Resource API for Javaを使用して、DOMオブジェクトをOracle XML DBリポジトリに保存できます。XML文書は次の適切な形式で格納されます。

  • BLOBインスタンス(スキーマに基づかない文書の場合)

  • XML Schemaで指定された形式(XML Schemaに基づく文書の場合)

例15-13では、Java DOM API for XMLTypeを使用してDOMオブジェクトを作成し、関連するXML Schemaで指定された形式で格納します。この例では、XML Schemaに対する検証は示されていません。

例15-13 Java DOM APIを使用したDOMオブジェクトの作成

import oracle.xdb.XMLType;
...
OraclePreparedStatement stmt = 
    (OraclePreparedStatement) conn.prepareStatement(
        "update po_xml_XMLTypetab 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

XMLTypeインスタンスは、oracle.xdb.XMLTypeによってJavaで表現されます。XMLTypeインスタンスがJDBCを使用してフェッチされると、このインスタンスは提供されたXMLTypeクラスのオブジェクトとして自動的に明示されます。同様に、このクラスのオブジェクトは、データ操作言語(DML)文の値としてバウンドできます。通常、この値はXMLTypeです。SQLJクライアントでも同じ動作がサポートされます。

Java DOM API for XMLTypeのクラス

Oracle XML DBは、W3CのDOMレベル2勧告をサポートします。W3C勧告に加えて、Oracle XML DB DOM APIは、アプリケーションとOracle XML Developer's Kit for Javaの相互作用を円滑にするOracle固有の拡張機能も提供します。Oracleの拡張機能のリストは、次のURLを参照してください。

http://www.oracle.com/technetwork/database-features/xmldb/overview/index.html

XMLDocumentは、インスタンス化されたXML文書用のDOMを表すクラスです。XMLTypeの値は、Documentの引数を取るXMLTypeコンストラクタを使用してXML文書から取得できます。

XMLType createXML(Connection conn, Document domdoc)

表15-1に、Java DOM API for XMLTypeのクラスおよび実装されるW3CのDOMインタフェースを示します。Java DOM APIクラスはすべて、oracle.xml.parser.v2パッケージに入っています。

表15-1 Java DOM API for XMLType: クラス

Java DOM API for XMLTypeのクラス W3CのDOMインタフェース勧告のクラス
XMLDocument
org.w3c.dom.Document 
XMLCDATA
org.w3c.dom.CDataSection 
XMLComment
org.w3c.dom.Comment 
XMLPI
org.w3c.dom.ProcessingInstruction 
XMLText 
org.w3c.dom.Text 
XMLEntity
org.w3c.dom.Entity 
DTD
org.w3c.dom.DocumentType 
XMLNotation
org.w3c.dom.Notation 
XMLAttr
org.w3c.dom.Attribute 
XMLDomImplementation
org.w3c.dom.DOMImplementation 
XMLElement
org.w3c.dom.Element 
XMLAttrList
org.w3c.dom.NamedNodeMap 
XMLNode 
org.w3c.dom.Node 

推奨またはサポートされていないJavaメソッド

リリース2(9.2.0.1)のマニュアルには次のメソッドに関する説明が含まれていますが、サポートされなくなりました。

  • XDBDocument.getElementByID

  • XDBDocument.importNode

  • XDBNode.normalize

  • XDBNode.isSupported

  • XDBDomImplementation.hasFeature

また、Oracle Database 11gリリース1以前は、oracle.xdb.domパッケージの異なるAPIがJava DOMに使用されていました。非推奨になったAPIの詳細は、該当リリースのドキュメントを参照してください。oracle.xdb.domの次のクラスは、非推奨です。かわりにoracle.xml.parser.v2クラスを使用してください。

  • XDBAttribute: XMLAttrを使用

  • XDBBinaryDocument

  • XDBCData: XMLCDATAを使用

  • XDBComment: XMLCommentを使用

  • XDBDocFragment: XMLDocumentFragmentを使用

  • XDBDocument: XMLDocumentを使用

  • XDBDocumentType: DTDを使用

  • XDBDOMException: XMLDomExceptionを使用

  • XDBDomImplementation: XMLDomImplementationを使用

  • XDBElement: XMLElementを使用

  • XDBEntity: XMLEntityを使用

  • XDBEntityReference: XMLEntityReferenceを使用

  • XDBNamedNodeMap: XMLAttrListを使用

  • XDBNode: XMLNodeを使用

  • XDBNodeList: NodeListを使用

  • XDBNotation: XMLNotationを使用

  • XDBProcInst: XMLPIを使用

  • XDBText: XMLTextを使用

Java DOM API for XMLTypeの使用

図15-1に、Java DOM API for XMLTypeを示します脚注1 。次の手順を実行します。

  1. XMLType表または表のXMLType列からXMLデータを取り出します。XMLデータをフェッチすると、OracleによってXMLTypeのインスタンスが作成されます。これによって、getDocument()メソッドを使用して文書のインスタンスを取得できます。その後、Java DOM API for XMLTypeを使用してDOMツリーの要素を操作できます。

  2. Java DOM API for XMLTypeを使用してDOMツリーの要素を操作します。変更されたデータはXMLTypeインスタンスに格納されますが、データはJDBC更新を使用して戻されます。

XMLTypeおよびXMLDocumentインスタンスは、各クラスでclose()メソッドを使用してクローズする必要があります。クローズすると、保持されていた基礎となるメモリーがすべて解放されます。

図15-1 Java DOM API for XMLTypeの使用

図15-1の説明が続きます。
「図15-1 Java DOM API for XMLTypeの使用」の説明

Javaを使用した大規模ノードの処理

Oracle Database 11gリリース1 (11.1)以前は、ノードのサイズが64KB未満に制限されていました。ノード値を設定および取得するJavaメソッドはjava.lang.String型の引数のみでサポートされているためです。文字列の最大サイズはJava VMの実装により依存していますが、限定されています。リリース11.1以前は、oracle.xdb.dom.XDBNode.javaクラス内に含まれているノード値を管理するJava DOM APIは次のようになっていました。

public String getNodeValue ();
public void setNodeValue (String value);

以前は、oracle.xdb.dom.XDBAttribute.javaクラス内に含まれている属性を管理するJava DOM APIは次のようになっていました。

public String getValue ();
public void setValue (String value);

Oracle Database 11gリリース1 (11.1)から、パッケージoracle.xdb.domは非推奨になっています。このパッケージ内のJavaクラスXDBNodeおよびXDBAttributeは、パッケージoracle.xml.parser.v2内でそれぞれクラスXMLNodeおよびXMLAttrに置き換えられています。また、これらのDOM APIはリリース11.1では拡張され、任意のサイズのテキスト・ノード値およびバイナリ・ノード値をサポートしています。


注意:

大規模ノード機能は、Thickまたはkprb接続でのみ動作します。Thin接続では動作しません。


関連項目:


Java DOMへのストリーム拡張

Java StringReader、およびWriterデータはすべてUCS2で表現されます。これは、データベース・キャラクタ・セットと同じではない場合があります。また、ノード文字データはキャラクタ・セットIDでタグ付けされており、ノード値が移入するときに設定されます。

次に示すoracle.xml.parser.v2.XMLNode.javaのメソッドにより、サイズが64KBを超えるノードにアクセスできます。リーフ・ノード(属性、PICDATAなど)ではないノードを取得または設定しようとすると、これらのAPIにより例外が発生します。また、その値を実際に書き込み、ノードへのストリーム・アクセス状態を維持する場合に使用するリソースを解放するclose()を使用してください。

Get-Pullモデル

バイナリ入力ストリームの場合:

public java.io.InputStream getNodeValueAsBinaryStream () 
       throws java.io.IOException, DOMException;

メソッドgetNodeValueAsBinaryStream()は、このクラスの定義メソッドを使用して読み取ることができるjava.io.InputStreamのインスタンスを戻します。ノードのデータ型はRAWまたはBLOBである必要があります。それ以外の場合は、IOExceptionが発生します。次の例では、バイナリ50バイトのセグメントのノード値を読み取っています。

...
oracle.xml.parser.v2.XMLNode node = null;
...
 
java.io.InputStream value = node.getNodeValueAsBinaryStream ();
// now read InputStream...
byte buffer [] = new byte [50];
int returnValue = 0;
while ((returnValue = value.read (buffer)) != -1)
{
   // process next 50 bytes of node
}
...

文字入力ストリームの場合:

public java.io.Reader getNodeValueAsCharacterStream() 
       throws java.io.IOException, DOMException;

メソッドgetNodeValueAsCharacterStream()は、このクラスの定義メソッドを使用して読み取ることができるjava.io.Readerのインスタンスを戻します。ノードのデータ型が文字でもCLOBでもない場合、まずノード・データは文字に変換されます。すべてのノード・データは最終的には文字形式になり、必要に応じてUCS2に変換されます。次の例では、50文字のセグメントのノード値を読み取っています。

...
oracle.xml.parser.v2.XMLNode node = null;
...
 
java.io.Reader value = node.getNodeValueAsCharacterStream ();
// now read InputStream
char buffer [] = new char [50];
int returnValue = 0;
while ((returnValue = value.read (buffer)) != -1)
{
   // process next 50 characters of node
}
...

Get-Pushモデル

バイナリ出力ストリームの場合:

public void getNodeValueAsBinaryStream (java.io.OutputStream pushValue) 
       throws java.io.IOException,  DOMException;

pushValueで指定されるjava.io.OutputStreamの状態はopenである必要があります。ノードのデータ型はRAWまたはBLOBである必要があります。それ以外の場合は、IOExceptionが発生します。ノード・バイナリ・データはOutputStreamwrite()メソッドを使用してpushValueに書き込まれ、ノード値が完全にストリームに書き込まれるとclose()メソッドがコールされます。

文字出力ストリームの場合:

public void getNodeValueAsCharacterStream (java.io.Writer pushValue) 
       throws java.io.IOException, DOMException;

pushValueで指定されるjava.io.Writerの状態はopenである必要があります。ノードのデータ型が文字でもCLOBでもない場合、まずデータは文字に変換されます。常に文字形式のノード・データは必要に応じてUCS2に変換され、java.io.Writerにプッシュされます。

Set-Pullモデル

バイナリ入力ストリームの場合:

public void setNodeValueAsBinaryStream (java.io.InputStream pullValue) 
       throws java.io.IOException, DOMException;

pullValueで指定されるjava.io.InputStreamの状態はopenである必要があります。ノードのデータ型はRAWまたはBLOBである必要があります。それ以外の場合は、IOExceptionが発生します。pullValueのバイナリ・データ全体がInputStreamread()メソッドを使用して読み取られ、ノード値を置換します。

import java.io.InputStream;
import oracle.xml.parser.*;
...
oracle.xml.parser.v2.XMLNode node = null;
...
byte [] buffer = new byte [500];
java.io.InputStream  istream; //user-defined input stream
node.setNodeValueAsBinaryStream (istream);

文字入力ストリームの場合:

public void setNodeValueAsCharacterStream (java.io.Reader pullValue) 
       throws java.io.IOException, DOMException;

pullValueで指定されるjava.io.Readerの状態はopenである必要があります。ノードのデータ型が文字でもCLOBでもない場合、文字データはUCS2からノード・データ型に変換されます。ノードのデータ型が文字またはCLOBの場合、pullValueから読み取られた文字データは、UCS2からノードのキャラクタ・セットに変換されます。

Set-Pushモデル

バイナリ出力ストリームの場合:

public java.io.OutputStream setNodeValueAsBinaryStream () 
     throws java.io.IOException, DOMException;

メソッドsetNodeValueAsBinaryStream()は、コール元によるノード値の書込み先となるjava.io.OutputStreamのインスタンスを戻します。ノードのデータ型はRAWまたはBLOBである必要があります。それ以外の場合は、IOExceptionが発生します。次の例では、Oracle XML DBまたはOracle XML Developer's Kitが提供するjava.io.OutputStreamの実装に書き込むことで、ノード値をバイナリ・データに設定しています。

文字出力ストリームの場合:

public java.io.Writer setNodeValueAsCharacterStream () 
       throws java.io.IOException, DOMException;

メソッドsetNodeValueAsCharacterStream()は、コール元によるノード値の書込み先となるjava.io.Writerのインスタンスを戻します。書き込まれた文字データはまず、必要に応じてUCS2からノードのキャラクタ・セットに変換されます。ノードのデータ型が文字でもCLOBでもない場合、文字データはノード・データ型に変換されます。同様に、次の例では、Oracle XML DBまたはOracle XML Developer's Kitが提供するjava.io.Writerの実装に書き込むことで、ノード値を文字データに設定しています。

import java.io.Writer;
import oracle.xml.parser.*;
...
oracle.xml.parser.v2.XMLNode node = null;
...
char [] buffer = new char [500];
java.io.Writer  writer = node.setNodeValueAsCharacterStream ();
for (int k = 0; k < 10; k++)
  {
    byte segment [] = new byte [50];
    // copy next subset of buffer into segment
    writer.write (segment);
  }
writer.flush ();
writer.close();

関連項目:

  • 『Oracle Database XML Java API Reference』

  • 大規模ノードのためのC関数の詳細は、『Oracle Database XML C APIリファレンス』を参照してください。


Oracle XML DBはwriterまたはOutputStreamを作成し、それをノード値が完全に書き込まれるまで繰り返しwrite()メソッドをコールするユーザーに渡します。新規ノード値は、ユーザーがclose()メソッドをコールするときのみ反映されます。

バイナリXMLでのJava DOM APIおよびJDBCの使用

XMLデータはXMLTypeを使用してOracle XML DBに格納でき、この抽象データ型の記憶域モデルの1つはバイナリXMLです。バイナリXMLはXMLデータの簡潔な、XML Schema対応のエンコーディングです。データベース内のXMLTypeの記憶域モデルとして使用することができますが、データベース外にあるXMLデータに対しても使用することができます。XMLデータのクライアント側処理には、Oracle XML DB内に格納されているデータや、データベース外に存在する一時データが関わることがあります。

Java DOM APIを使用して、Oracle XML DBに対して、バイナリXML形式でエンコードされたXMLデータを読書きすることができます。この処理には通常の読書きプロシージャが関与します。

バイナリXMLはXML Schemaに対応しており、必要性とデータに応じて、各種のコード体系を使用することができます。このため、バイナリXMLデータを操作するためには、関連するXML Schemaとエンコーディングについて、データとこのメタデータの両方が必要です。

データベースに格納されているXMLTypeデータの場合、このメタデータもデータベースに格納されます。ただし、データベースとデータのセットアップに応じて、メタデータが適用されるデータと同一のサーバーにメタデータが格納されない場合があります。この場合、データベースに対してバイナリXMLデータを読書きするためには、次の手順を実行する必要があります。

  1. メタデータのコンテキスト・インスタンスを作成します。

  2. このコンテキストを、データベース内のバイナリXMLデータにアクセスするために使用するデータ接続に関連付けます。データ接続は、専用接続でも接続プールでもかまいません。クラスjava.sql.ConnectionのメソッドgetDedicatedConn()およびgetConnPool()を使用して、それらの接続の型に応じて、これら2つの接続型へのハンドルを取得します。

すると、アプリケーションがデータ接続上でバイナリXMLデータをエンコードまたはデコードする必要がある場合、それに必要なメタデータが自動的にフェッチされます。一連の動作の全体は次のとおりです。

  1. クラスjava.sql.ConnectionにXMLデータ接続オブジェクトを作成します。

  2. パッケージoracle.xml.binxml内のメソッドBinXMLMetadataProviderFactory.createDBMetadataProvider()を使用して、必要に応じて1つ以上のメタデータ・コンテキストを作成します。メタデータ・コンテキストは、メタデータ・リポジトリと呼ばれることもあります。メタデータ・コンテキストは、専用接続または接続プールから作成することができます。

  3. メタデータ・コンテキストをバイナリXMLデータ接続に関連付けます。これには、パッケージoracle.xml.binxml内のメソッドDBBinXMLMetadataProvider.associateDataConnection()を使用します。

  4. (オプション) XMLデータがデータベース外に由来するものの場合は、メソッドoracle.xdb.XMLType.setFormatPref()を使用して、データベースに送信されるXMLデータがバイナリXML形式でエンコードされるように指定します。これは、DOM文書(クラスoracle.xdb.XMLType)に適用されます。バイナリXMLを指定しない場合、データはテキストとしてデータベースに送信されます。

  5. 通常のJavaメソッドを使用して、データベースに対してXMLデータを読書きします。バイナリXML文書のエンコードやデコードに必要なときは常に、メタデータ・コンテキストを使用して、必要なメタデータが自動的にフェッチされます。

    Java DOM API for XMLを使用して、クライアント・レベルのXMLデータに対して操作します。

例15-14に、これを示します。

例15-14 バイナリXMLでのJava DOM APIの使用

import java.sql.*;
import oracle.jdbc.*;
import oracle.jdbc.pool.OracleDataSource;
import oracle.xdb.XMLType;
import oracle.xml.binxml.*;
 
class tdadxdbxdb11jav001 {
  public static void printBinXML() throws SQLException, BinXMLException
  {
    // Create datasource to connect to local database
    OracleDataSource ods = new OracleDataSource();
    ods.setURL("jdbc:oracle:kprb");
    System.out.println("Starting Binary XML Java Example");
    // Create data connection
    Connection conn = ods.getConnection();
    // Create binary XML metadata context, using connection pool
    DBBinXMLMetadataProvider repos =
      BinXMLMetadataProviderFactory.createDBMetadataProvider();
    repos.setConnectionPool(ods);
    // Associate metadata context with data connection
    repos.associateDataConnection(conn);
    // Query XML data stored in XMLType column as binary XML
    Statement stmt = conn.createStatement();
    ResultSet rset = stmt.executeQuery("SELECT doc FROM po_binxmltab");
    // Get the XMLType object
    while (rset.next())
    {
      XMLType xmlobj = (XMLType) rset.getObject(1);
      // Perform XMLType operation
      String xmlvalue = xmlobj.getStringVal();
      System.out.println(xmlvalue);
    }
    // Close result set, statement, and connection
    rset.close();
    stmt.close();
    conn.close();
    System.out.println("Completed Binary XML Java Example");
  }
}

関連項目:




脚注の凡例

脚注1: ここでは、XMLデータがXML Schemaに登録済であり、XMLTypeの列に格納されていると想定しています。