この章では、XQuery API for Java (XQJ)を使用してOracle XML DBにアクセスする方法について説明します。
内容は次のとおりです。
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 Packages
に関する項を参照してください
XQuery 1.0: An XML Query Language (Second Edition)は、http://www.w3.org/TR/xquery/
にあります
XQuery API for Java (XQJ) 1.0仕様(2009年3月) https://jcp.org/aboutJava/communityprocess/final/jsr225/
この仕様には、わかりやすい例が含まれており、非常に具体的です。
Oracle XML DBでXQJを使用するには、Javaランタイム環境1.6が必要です。
さらに、「XQuery Processor for Javaの概要」にリストされている必須Java Archive (JAR)ファイルおよび次のJARファイルが、CLASSPATH
環境変数に含まれている(またはコマンドライン・オプションclasspath
を使用して渡される)必要があります。
jdbc/lib/ojdbc6.jar
rdbms/jlib/xdb6.jar
これらのJARファイルのディレクトリ・パスは、データベース・インストールのORACLE_HOME
ディレクトリへの相対パスです。
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(); } } }
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でのXQuery言語の使用については、『Oracle XML DB開発者ガイド』を参照してください。
Oracle XML DBでのXQJのサポートには、次の制約があります。これらの制約は、中間層のXQueryエンジンでの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を含む)にする必要があります。この範囲外の年を使用すると、エラーまたは予期しない結果が生じる可能性があります。
データベースから項目シーケンスをフェッチするには、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変数がこれらのデータにバインドされます。