16 XQuery API for Javaを使用したOracle XML DBへのアクセス
XQuery API for Java (XQJ)を使用してOracle XML DBにアクセスする方法について説明します。
16.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の一般的な情報についてはとりあげません。
関連項目:
-
XQueryの機能およびOracle XML DBでのサポートなどOracle XML DBの詳細は、『Oracle XML DB開発者ガイド』を参照してください
-
関連するAPIドキュメントについては、Oracle Database XML Java APIリファレンスの
XQueryパッケージ
に関する項を参照してください -
JSR-000225 XQuery API for Java。この仕様には、わかりやすい例が含まれており、非常に具体的です
16.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
ディレクトリへの相対パスです。
16.2 例: XQJを使用したOracle XML DBの問合せ
次の例では、XQJを使用してOracle XML DBのデータを問い合せて取得する方法を示します。
例16-1に、XQJを使用してOracle XML DBの表からデータを問い合せる方法を示します。Order Entry (OE)データベース・サンプル・スキーマのWAREHOUSES
表を使用します。OEサンプル・スキーマのWAREHOUSES
表には、倉庫情報を持つXML文書が含まれます。WAREHOUSES
表には、XMLType列warehouse_spec
およびその他の列が含まれます。(この例で使用されるデータの詳細は、『Oracle XML DB開発者ガイド』の標準データベース・スキーマに関する項を参照してください。)
例16-1では特に、次のステップを実行する方法を示します。
-
Oracle XML DBへのXQJ接続の取得
XQJを使用してOracle XML DBに接続するプログラムはすべて、まず
OXQDDataSource
オブジェクトを作成する必要があります。次に、必須プロパティ値でOXQDDataSource
を初期化してから、Oracle XML DBインスタンスへのXQJ接続を取得します。 -
XQuery式の準備
-
評価のためのXQuery式の送信
-
生成されたXQueryシーケンスの各項目の印刷
例16-1では、XQuery式はUniversal Resource Identifier (URI)スキームoradb
を介してWAREHOUSES
表にアクセスします。(XQueryを使用したXML DBでの表の問合せまたはデータの表示の詳細は、『Oracle XML DB開発者ガイド』のURIスキームoradb
に関する項を参照してください。)
例16-1では、XQJで外部変数値をバインドする方法も示します。問合せには、WAREHOUSES
表から戻された行をWAREHOUSE_ID
でフィルタリングするための外部変数$x
があります。
例16-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>
例16-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リポジトリのデータを問い合せることができます。例16-2に、XQuery内でfn:doc
関数を使用してリポジトリにアクセスする方法を示します。(これらのXQuery関数の使用の詳細は、『Oracle XML DB開発者ガイド』のOracle XML DBリポジトリのXMLデータの問合せに関する項を参照してください。)
例16-2で生成される出力は次のとおりです。
<emp ename="Jack" dept="Administration"/> <emp ename="Jill" dept="Marketing"/>
例16-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(); } } }
例16-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(); } } }
16.3 Oracle XML DBのXQJのサポート
2つのOracle XQJ実装は、いくつかの点で違いがあります。Oracle XML DBのXQJのサポートについて説明します。
XQJを使用した中間層のXQueryエンジンへのアクセスについては、「XQuery Processor for Javaの使用」で説明しています。
表16-1に、Oracle XML DBへの接続に使用するOXQDDataSourceプロパティを示します。Oracle XML DBへのXQJ接続を作成するには、これらのプロパティの値を設定する必要があります。dbname
プロパティまたはserviceName
プロパティの値、および表16-1にリストされているすべてのその他のOXQDDataSourceプロパティの値を設定する必要があります。
表16-1 OXQDDataSourceプロパティ
プロパティ | 値 | getメソッド | setメソッド |
---|---|---|---|
|
|
|
|
|
データベース・スキーマ(ユーザー)名 |
|
|
|
データベース・スキーマのパスワード |
|
|
|
データベース・インスタンスのホスト名 |
|
|
|
XQJ接続用のデータベース・インスタンスのポート番号 |
|
|
|
データベース・インスタンス名(サービスID)脚注 1 |
|
|
|
サービス名脚注1 |
|
|
脚注1
サービスIDまたはサービス名のいずれかを使用して、データベースを識別できます。
表16-2で、Oracle XML DBでのオプションのXQJ機能のサポートについて説明します。
注意:
Oracle XML DBによる一部のXQJ機能のサポートは、中間層のXQueryエンジンによるサポートとは異なります。特に、Oracle XML DB XQJ実装では、ユーザー定義タイプの使用をサポートしていません。
表16-2 Oracle XML DBでのオプションのXQJ機能のサポート
XQJ機能 | Oracle XML DBのサポート |
---|---|
|
|
JDBC接続 |
サポートされません。 |
|
表16-1を参照してください。 |
コマンド |
サポートされません。 |
|
サポートされません。 |
シリアライズ |
値 |
追加のStAXおよびSAXイベント |
サポートされません。 |
ユーザー定義スキーマ型 |
サポートされません。 |
ノードが外部変数にバインドされている場合の、ノードID、文書順、ノード・コンテキストの完全保持 |
サポートされません。 |
ログイン・タイムアウト |
サポートされません。 |
トランザクション |
サポートされません。 |
入力ノードが文書ノードでない場合の |
|
匿名タイプの |
|
|
|
入力が整形式XML文書でない場合の |
例外を呼び出します。 |
|
サポートされません。 |
インタフェース |
サポートされません。 |
XQDataSource.getConnection( java.sql.Connection) |
サポートされません。(JDBC接続はサポートされません。) |
XQDataSource.getConnection( java.lang.String, java.lang.String) |
引数なしの |
関連項目:
Oracle XML DBでのXQuery言語の使用の詳細は、『Oracle XML DB開発者ガイド』を参照してください
16.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を含む)にする必要があります。この範囲外の年を使用すると、エラーまたは予期しない結果が生じる可能性があります。
16.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変数がこれらのデータにバインドされます。