8 XQuery API for Javaを使用したOracle XML DBへのアクセス
XQuery API for Java (XQJ)を使用してOracle XML DBにアクセスする方法について説明します。
トピック:
- Oracle XML DBのXQJのサポートの概要
XQuery API for Java (XQJ) (JSR-225とも呼ばれる)は、JavaプログラムからXQueryを使用してExtensible Markup Language (XML)データにアクセスするための業界標準の方法を提供します。これにより、XMLのデータ・ソースに対してXQuery式を評価したり、その結果をXMLデータとして処理できます。 - 例: XQJを使用したOracle XML DBの問合せ
次の例では、XQJを使用してOracle XML DBのデータを問い合せて取得する方法を示します。 - Oracle XML DBのXQJのサポート
2つのOracle XQJ実装は、いくつかの点で違いがあります。Oracle XML DBのXQJのサポートについて説明します。 - Oracle XML DBで使用する際のXQJのパフォーマンスに関する考慮事項
データベースから項目シーケンスをフェッチするには、XQResultSequenceメソッドnext()を使用して一度に1つずつ項目を取得してから、XQItemAccessorメソッドを使用してそれらの項目に対応するすべてのデータをフェッチします。
8.1 Oracle XML DBのXQJのサポートの概要
XQuery API for Java (XQJ)(JSR-225とも呼ばれる)は、JavaプログラムからXQueryを使用してExtensible Markup Language (XML)データにアクセスするための業界標準の方法を提供します。これにより、XMLのデータ・ソースに対してXQuery式を評価したり、その結果をXMLデータとして処理できます。
Oracleでは、XQuery式を評価するための2つのXQueryエンジンが用意されています。1つはOracle XML DBにあり、データベースのXMLデータで使用し、もう1つはOracle XML Developer's Kit (XDK)にあり、データベース外部のXMLデータで使用します。(XDK用のXQueryエンジンについては、「XQuery Processor for Javaの使用」を参照してください)。
Oracleでは、これら2つのXQueryエンジンにアクセスするために、2つのXQJ実装が用意されています。これらの実装は両方ともXDKに含まれており、データがデータベース内にある場合でもその他の場所にある場合でも、この実装によりXDKを使用して標準XQJ APIでXMLデータにアクセスできます。
XQJで実行される問合せは、Oracle XML DBでサポートされる標準のWorld Wide Web Consortium (W3C) XQuery 1.0言語で記述されます。この機能の一般的なユースケースは、ローカルのJavaプログラムからリモートのデータベース(Oracle XML DB)に格納されているXMLデータにアクセスすることです。
このドキュメントでは、XQueryおよびXQJの一般的な情報についてはとりあげません。
トピック:
- XQJを使用したOracle XML DBへのアクセスの前提条件
Oracle XML DBでXQJを使用するには、Javaランタイム環境1.6が必要です。また、特定のJavaアーカイブ(JAR)ファイルをCLASSPATH環境変数に指定するか、コマンドライン・オプションclasspathを使用して渡す必要があります。
関連項目:
-
XQueryの機能およびOracle XML DBでのサポートなどOracle XML DBの詳細は、『Oracle XML DB開発者ガイド』を参照してください
-
関連するAPIドキュメントについては、Oracle Database XML Java APIリファレンスの
XQueryパッケージに関する項を参照してください -
JSR-000225 XQuery API for Java。この仕様には、わかりやすい例が含まれており、非常に具体的です
8.1.1 XQJを使用したOracle XML DBへのアクセスの前提条件
Oracle XML DBでXQJを使用するには、Javaランタイム環境1.6が必要です。また、特定のJavaアーカイブ(JAR)ファイルをCLASSPATH環境変数に指定するか、コマンドライン・オプションclasspathを使用して渡す必要があります。
JARファイルは次のとおりです。
-
「XQuery Processor for Javaの概要」に示されている必須JARファイル
-
jdbc/lib/ojdbc6.jar -
rdbms/jlib/xdb6.jar
これらのJARファイルのディレクトリ・パスは、データベース・インストールのORACLE_HOMEディレクトリへの相対パスです。
8.2 例: XQJを使用したOracle XML DBの問合せ
次の例では、XQJを使用してOracle XML DBのデータを問い合せて取得する方法を示します。
例8-1に、XQJを使用してOracle XML DBの表からデータを問い合せる方法を示します。Order Entry (OE)データベース・サンプル・スキーマのWAREHOUSES表を使用します。OEサンプル・スキーマのWAREHOUSES表には、倉庫情報を持つXML文書が含まれます。WAREHOUSES表には、XMLType列warehouse_specおよびその他の列が含まれます。(この例で使用されるデータの詳細は、『Oracle XML DB開発者ガイド』の標準データベース・スキーマに関する項を参照してください。)
例8-1では特に、次の手順を実行する方法を示します。
-
Oracle XML DBへのXQJ接続の取得
XQJを使用してOracle XML DBに接続するプログラムはすべて、まず
OXQDDataSourceオブジェクトを作成する必要があります。次に、必須プロパティ値でOXQDDataSourceを初期化してから、Oracle XML DBインスタンスへのXQJ接続を取得します。 -
XQuery式の準備
-
評価のためのXQuery式の送信
-
生成されたXQueryシーケンスの各項目の印刷
例8-1では、XQuery式はUniversal Resource Identifier (URI)スキームoradbを介してWAREHOUSES表にアクセスします。(XQueryを使用したXML DBでの表の問合せまたはデータの表示の詳細は、『Oracle XML DB開発者ガイド』のURIスキームoradbに関する項を参照してください。)
例8-1では、XQJで外部変数値をバインドする方法も示します。問合せには、WAREHOUSES表から戻された行をWAREHOUSE_IDでフィルタリングするための外部変数$xがあります。
例8-1で生成される出力は次のとおりです(読みやすくするために再フォーマット済です)。
<Warehouse><Building>Owned</Building><Area>25000</Area><Docks>2</Docks> <DockType>Rearload</DockType><WaterAccess>Y</WaterAccess> <RailAccess>N</RailAccess><Parking>Street</Parking> <VClearance>10 ft</VClearance></Warehouse> <Warehouse><Building>Rented</Building><Area>50000</Area><Docks>1</Docks> <DockType>Sideload</DockType><WaterAccess>Y</WaterAccess> <RailAccess>N</RailAccess><Parking>Lot</Parking> <VClearance>12 ft</VClearance></Warehouse>
例8-2に、XQJを使用してOracle XML DBリポジトリからデータを取得する方法を示します。この例では、depts.xmlとemps.xmlの2つのファイルがXML DBリポジトリのフォルダ/publicの下にアップロードされていると想定しています。たとえば、FTPを使用して2つのファイルをOracle XML DBリポジトリにアップロードできます。(Oracle XML DBリポジトリへのデータの格納およびOracle XML DBリポジトリの使用の詳細は、『Oracle XML DB開発者ガイド』のOracle XML DBリポジトリの使用に関する項を参照してください。)
depts.xmlの内容は次のとおりです。
depts.xml:
<?xml version="1.0"?>
<depts>
<dept deptno="10" dname="Administration"/>
<dept deptno="20" dname="Marketing"/>
<dept deptno="30" dname="Purchasing"/>
</depts>
emps.xmlの内容は次のとおりです。
emps.xml:
<?xml version="1.0"?>
<emps>
<emp empno="1" deptno="10" ename="John" salary="21000"/>
<emp empno="2" deptno="10" ename="Jack" salary="310000"/>
<emp empno="3" deptno="20" ename="Jill" salary="100001"/>
</emps>
fn:docおよびfn:collection関数を使用して、XQueryでOracle XML DBリポジトリのデータを問い合せることができます。例8-2に、XQuery内でfn:doc関数を使用してリポジトリにアクセスする方法を示します。(これらのXQuery関数の使用の詳細は、『Oracle XML DB開発者ガイド』のOracle XML DBリポジトリのXMLデータの問合せに関する項を参照してください。)
例8-2で生成される出力は次のとおりです。
<emp ename="Jack" dept="Administration"/> <emp ename="Jill" dept="Marketing"/>
例8-1 XQJを使用したXQueryでのXML DB表の問合せ
import oracle.xml.xquery.xqjdb.OXQDDataSource;
import javax.xml.xquery.XQItemType;
import javax.xml.xquery.XQResultSequence;
import javax.xml.xquery.XQConnection;
import javax.xml.xquery.XQPreparedExpression;
import javax.xml.namespace.QName;
public class example1
{
public static void main(String argv[])
{
try
{
// Create a new OXQDDataSource for connecting to Oracle XML DB
OXQDDataSource oxqDS = new OXQDDataSource();
// Set appropriate connection information for the database instance.
// Must use the thin driver
oxqDS.setProperty("driver", "jdbc:oracle:thin");
oxqDS.setProperty("dbusername", "oe");
oxqDS.setProperty("dbpassword", "oe");
// Machine hostname
oxqDS.setProperty("dbserver", "myserver");
// Database instance port number
oxqDS.setProperty("dbport", "6479");
// Database instance port number
oxqDS.setProperty("serviceName", "mydbinstance");
XQConnection conn = oxqDS.getConnection();
XQItemType itemTypeInt = conn.createAtomicType(XQItemType.XQBASETYPE_INT);
XQPreparedExpression expr = conn.prepareExpression("declare variable $x as
xs:int external; for $i in fn:collection('oradb:/OE/WAREHOUSES') where
$i/ROW/WAREHOUSE_ID < $x return $i/ROW/WAREHOUSE_SPEC/Warehouse");
expr.bindInt(new QName("x"), 3, itemTypeInt);
XQResultSequence xqSeq = expr.executeQuery();
while (xqSeq.next())
System.out.println (xqSeq.getItemAsString(null));
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
例8-2 XQJを使用したXQueryでのXML DBリポジトリの問合せ
import oracle.xml.xquery.xqjdb.OXQDDataSource;
import javax.xml.xquery.XQItemType;
import javax.xml.xquery.XQResultSequence;
import javax.xml.xquery.XQConnection;
import javax.xml.xquery.XQPreparedExpression;
import javax.xml.namespace.QName;
public class example2
{
public static void main(String argv[])
{
try
{
// Create a new OXQDDataSource for connecting to Oracle XML DB
OXQDDataSource oxqDS = new OXQDDataSource();
// Set appropriate connection information for the database instance.
// Must use the thin driver
oxqDS.setProperty("driver", "jdbc:oracle:thin");
oxqDS.setProperty("dbusername", "oe");
oxqDS.setProperty("dbpassword", "oe");
// Machine hostname
oxqDS.setProperty("dbserver", "myserver");
// Database instance port number
oxqDS.setProperty("dbport", "6479");
// Database instance port number
oxqDS.setProperty("serviceName", "mydbinstance");
XQConnection conn = oxqDS.getConnection();
XQPreparedExpression expr = conn.prepareExpression("for $e in
doc(\"/public/emps.xml\")/emps/emp let $d :=
doc(\"/public/depts.xml\")//dept[@deptno = $e/@deptno]/@dname where
$e/@salary > 100000 order by $e/@empno return
<emp ename=\"{$e/@ename}\" dept=\"{$d}\"/>");
XQResultSequence xqSeq = expr.executeQuery();
while (xqSeq.next())
System.out.println (xqSeq.getItemAsString(null));
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
8.3 Oracle XML DBのXQJのサポート
2つのOracle XQJ実装は、いくつかの点で違いがあります。Oracle XML DBのXQJのサポートについて説明します。
XQJを使用した中間層のXQueryエンジンへのアクセスについては、「XQuery Processor for Javaの使用」で説明しています。
表8-1に、Oracle XML DBへの接続に使用するOXQDDataSourceプロパティを示します。Oracle XML DBへのXQJ接続を作成するには、これらのプロパティの値を設定する必要があります。dbnameプロパティまたはserviceNameプロパティの値、および表8-1にリストされているすべてのその他のOXQDDataSourceプロパティの値を設定する必要があります。
表8-1 OXQDDataSourceプロパティ
| プロパティ | 値 | getメソッド | setメソッド |
|---|---|---|---|
|
|
|
|
|
|
|
データベース・スキーマ(ユーザー)名 |
|
|
|
|
データベース・スキーマのパスワード |
|
|
|
|
データベース・インスタンスのホスト名 |
|
|
|
|
XQJ接続用のデータベース・インスタンスのポート番号 |
|
|
|
|
データベース・インスタンス名(サービスID)脚注 1 |
|
|
|
|
サービス名脚注1 |
|
|
脚注1
サービスIDまたはサービス名のいずれかを使用して、データベースを識別できます。
表8-2で、Oracle XML DBでのオプションのXQJ機能のサポートについて説明します。
注意:
Oracle XML DBによる一部のXQJ機能のサポートは、中間層のXQueryエンジンによるサポートとは異なります。特に、Oracle XML DB XQJ実装では、ユーザー定義タイプの使用をサポートしていません。
表8-2 Oracle XML DBでのオプションのXQJ機能のサポート
| XQJ機能 | Oracle XML DBのサポート |
|---|---|
|
|
|
|
JDBC接続 |
サポートされません。 |
|
|
表8-1を参照してください。 |
|
コマンド |
サポートされません。 |
|
|
サポートされません。 |
|
シリアライズ |
値 |
|
追加のStAXおよびSAXイベント |
サポートされません。 |
|
ユーザー定義スキーマ型 |
サポートされません。 |
|
ノードが外部変数にバインドされている場合の、ノードID、文書順、ノード・コンテキストの完全保持 |
サポートされません。 |
|
ログイン・タイムアウト |
サポートされません。 |
|
トランザクション |
サポートされません。 |
|
入力ノードが文書ノードでない場合の |
|
|
匿名タイプの |
|
|
|
|
|
入力が整形式XML文書でない場合の |
例外を呼び出します。 |
|
|
サポートされません。 |
|
インタフェース |
サポートされません。 |
XQDataSource.getConnection( java.sql.Connection) |
サポートされません。(JDBC接続はサポートされません。) |
XQDataSource.getConnection( java.lang.String, java.lang.String) |
引数なしの |
トピック:
- Oracle XML DB XQJサポートのその他の制約
Oracle XML DBのXQJのサポートの制限事項について説明します。これらは、中間層のXQueryエンジンによるXQJサポートには適用されません。
関連項目:
Oracle XML DBでのXQuery言語の使用の詳細は、『Oracle XML DB開発者ガイド』を参照してください
8.3.1 Oracle XML DB XQJサポートのその他の制約
Oracle XML DBのXQJのサポートの制限事項について説明します。これらは、中間層のXQueryエンジンによるXQJサポートには適用されません。
Oracle XML DBのXQJのサポートは、次のように制限されます。
-
Oracle XML DB XQueryサポートに対する制約はすべて、Oracle XML DBでのXQJのサポートにも適用されます。
-
XDK Document Object Model (DOM)のみサポートされます。他のDOMを使用するとエラーが発生する可能性があります。
-
Oracle XML DB XQJ実装は、他のXQJ実装(XDK JavaでのXQJの実装を含む)とは相互運用できません。(「相互運用可能」の意味については、XQJ標準(JSR-225)を参照してください。)
-
XQDataSourceメソッドgetLogWriterおよびsetLogWriterは効果がありません(無視されます)。 -
XQStaticContentメソッドgetBoundarySpacePolicy、setBoundarySpacePolicy、getDefaultCollationおよびsetDefaultCollationは効果がありません(無視されます)。 -
XQStaticContentメソッドの名前空間コピー・モードsetCopyNamespacesModPreserveおよびsetCopyNamespacesModeInheritは効果がありません(無視されます)。使用される値は常に、それぞれpreserveおよびinheritです。 -
XQDynamicContextメソッドを使用したDocumentFragmentオブジェクトのバインドはサポートされません。 -
タイプ
xs:durationの値はサポートされません。XQDynamicContextメソッドを使用してxs:durationをバインドしたり、xs:duration値にアクセスしたりすると、エラーが発生します。 -
xs:date、xs:dateTime、xs:gYearおよびxs:gYearMonth値の年は-4712から9999 (-4712と9999を含む)にする必要があります。この範囲外の年を使用すると、エラーまたは予期しない結果が生じる可能性があります。
8.4 Oracle XML DBで使用する際のXQJのパフォーマンスに関する考慮事項
データベースから項目シーケンスをフェッチするには、XQResultSequenceメソッドnext()を使用して一度に1つずつ項目を取得してから、XQItemAccessorメソッドを使用してそれらの項目に対応するすべてのデータをフェッチします。
これにより、次に示す全シーケンスをフェッチするメソッド(データを戻す前にシーケンス全体を生成)を使用するよりもパフォーマンスが向上します。
-
getSequenceAsStream() -
getSequenceAsString(java.util.Properties props) -
writeSequence(java.io.OutputStream os, java.util.Properties props) -
writeSequence(java.io.Writer ow, java.util.Properties props) -
writeSequenceToResult(javax.xml.transform.Result result) -
writeSequenceToSAX(org.xml.sax.ContentHandler saxhdlr)
たとえば、getSequenceAsStream()を起動すると、XQuery結果のすべてのシーケンス・データがデータベースからフェッチされた後に、そこからXMLStreamReaderインスタンスが生成され、ユーザーのプログラムに戻されます。
また、項目自体はストリーム可能でないことに注意してください。項目アクセッサ・メソッドは、常に項目全体を生成してから、項目の一部を出力します。
入力については、XQDynamicContextで定義されたすべてのバインド・メソッドは、入力データを完全に生成してからデータベースに渡します。
たとえば、bindDocument(javax.xml.namespace.QName varName, javax.xml.stream.XMLStreamReader value, XQItemType type)を起動すると、入力XMLStreamReaderインスタンスによって参照されるすべてのデータが処理されてから、外部XQuery変数がこれらのデータにバインドされます。