本文へジャンプ

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

送信されたすべての情報は安全です。

  • 閉じる [x]

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


送信されたすべての情報は安全です。

  • 閉じる [x]

多層にわたる XML のプログラミング: パフォーマンス、忠実性、そして開発の単純化のために中間層で XML を使用する

JDBC 4.0、SQLXML、そして WebSphere Application Server XML フィーチャー・パックを使用して、XML のみで構成されるソリューションを開発する

Andrew Spyker, STSM, WebSphere XML, SOA, Performance Architect, IBM
Photo of Andrew Spyker
Andrew Spyker は WebSphere Application Server 開発チームの STSM (Senior Technical Staff Member) として、3 つの主要な分野に取り組んでいます。まず 1 つはパフォーマンスの分野で、WebSphere Application Server パフォーマンス・チームのリーダーとしての 5 年間の経験を生かし、パフォーマンス・チームのアドバイザー役を務めています。また、SOA ランタイム・アーキテクトとして、特にベンチマーク・ストラテジー、パフォーマンス、XML 整合性を重点に WebSphere SOA ランタイム全体での操作の一貫性を担当しています。そして 3 つ目の分野として最も時間をかけているのが、WebSphere ポートフォリオの XML ストラテジーの考案および促進です。最近では、WebSphere Application Server XML フィーチャー・パックのチーフ・アーキテクトを務めました。
Bert Van Der Linden, DB2 XML Architect, IBM
Photo of Bert Van Der Linden
Bert Van Der Linden は 2001 年に IBM に入社し、最終的に 2006 年の DB2 9 リリースへと発展した DB2 pureXML の設計に携わりました。それと並行して多くの顧客とパートナーと交渉し、データベースにおける XML を説得してきました。その活動は、今でも積極的に続けています。IBM に入社する前に勤めていた新興企業、Propel では、スケーラブルな e-commerce アプリケーションをホストする無停止分散ミドルウェアの設計および実装にリーダーとして携わっていました。それ以前は長年 Tandem Computers に勤め、金融業界での多数の重大なアプリケーションを実行するデータベース、NonStop SQL に取り組んできました。

概要: この記事で、データベースおよび中間層で XML データを操作する手法として、パフォーマンスに優れた自然な手法を学んでください。記事では XML データベースと Atom サービスの XML データを統合する Web アプリケーションを例に、この手法を説明します。そしてこのようなアプリケーションを構築する手段として、XML データベース、JDBC 4.0 の SQLXML サポート、そして IBM® WebSphere® Application Server V7.0 Feature Pack for XML を使用します。

このシリーズの他の記事を見る

日付:  2010年 3月 31日 (公開: 2010年 3月 30日)
レベル:  中級 この記事の原文:  英語
アクティビティー: 6497 ビュー
お気軽にご意見・ご感想をお寄せください: 


2010年 3月 31日 ― 「参考文献」の先頭に 3 つの動画へのリンクを追加しました。

サンプル・アプリケーション: データベースを統合したブログ・チェッカー

以下に示す Web アプリケーションについて考えてみましょう。


図 1. データベースを統合したブログ・チェッカー
データベースを統合したブログ・チェッカーの図

上記の Web アプリケーションは、ブログ用 Web サービスで公開されたブログ・データを処理します。ブログ・データに含まれるのは、ブロガーが所有する全ブログの情報とブログに対するすべてのコメントの情報で、このデータは XML の一形式である Atom 形式で返されます (リスト 1 の例を参照)。この Web アプリケーションを使用すると、ブロガーは自分のブログに投稿されたコメントを素早く調べ、内容に問題があるコメントを削除することができます。Web アプリケーションはデータを XHTML の Web ページおよびフォームに表示します。データのソースは XML 形式であり、ブラウザーのデータも同じく XML 形式 (HTML または XHTML) であることを考えると、XML データをそのままの形で操作するのが自然なことです。


リスト 1. Atom XML コメント・フィードの例

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="text">WebSphere Community Blog</title>
  ...
  <entry>
    <id>tag:blogger.com,1999:blog-1417695962027703953.post-6498982274841848264</id>
    <published>2009-10-17T13:06:00.000-05:00</published>
    <updated>2009-10-17T13:06:00.000-05:00</updated>
    <atom:title xmlns="" xmlns:atom="http://www.w3.org/2005/Atom" type="text">
      Questionable spamming comment title
    </atom:title>
    <atom:content xmlns="" xmlns:atom="http://www.w3.org/2005/Atom" type="html">
      Questionable spamming comment content
    </atom:content>
    ...
    <atom:author xmlns="" xmlns:atom="http://www.w3.org/2005/Atom">
      <atom:name>Joe Smith</atom:name>
      <atom:uri>http://joe.uri.com</atom:uri>
      <atom:email>jsmith@email.com</atom:email>
    </atom:author>
  </entry>
  ...
</feed>

ブロガーがやがて、問題のあるコメントが (リスト 1atom:author 要素に示されるような) 同じユーザーから、あるいは同じドメイン・ネームから送信されていることに気付いたとします。この時点で Web アプリケーションに変更を加え、ブロガーがコメントを削除する際に、そのコメントを送信したユーザーまたはドメインをスパマーとしてフラグを立てられるようにします。この情報はオリジナルのコメント用 Web サービスには保管されないため、データ・ストアに保持しなければなりません。データはすでに XML 形式になっているので、このデータは XML データベースに保持するのが自然です。そうすれば、今後このアプリケーションを使用して、特定のスパマーに関する統計情報をレポートし、どのコメントを削除するべきか提案することができます。

アプリケーションを実装する最善の方法とは

データベースが XML をネイティブにサポートするようになる以前は、XML データの処理には通常 2 つの方法が使われていました。1 つはデータをストリングにシリアライズしてからキャラクター・ラージ・オブジェクト (CLOB) としてデータベースに保管するという方法です。この方法にはパフォーマンス上の問題があると同時に、このデータをデータベース内で XML としてクエリーの対象にすることができません。

よく使われる頭字語

  • API: Application program interface
  • DOM: Document Object Model
  • HTML: Hypertext Markup Language
  • HTTP: Hypertext Transfer Protocol
  • JAXP: Java for XML Processing
  • JDBC: Java Database Connectivity
  • SAX: Simple API for XML
  • SOA: Service-oriented architecture
  • SQL: Structured Query Language
  • URI: Uniform Resource Identifier
  • URL: Uniform Resource Locator
  • W3C: World Wide Web Consortium
  • WSDL: Web Services Description Language
  • XHTML: Extensible Hypertext Markup Language
  • XML: Extensible Markup Language
  • XSLT: Extensible Stylesheet Language Transformations

もう 1 つの方法は、データをシュレッドし、XML データの構造におおよそ相当するリレーショナル・テーブルにマッピングするというものです。リレーショナル・データと XML データの表現方法は一致しないことから、この方法には忠実性に関して問題があります。また、マッピングのコードはユーザーが保守する必要があり、さらに前述の方法と同じくネイティブ XML に対するクエリーは行えません。それに加え、新しい要件によって XML データ・スキーマに変更があった場合、それに応じてリレーショナル・マッピングを変更するのに手間がかかるのが常です。

企業での XML の普及を受け、データベースは今や、リレーショナル・データだけでなく XML データも保管するようになってきています。XML データはそのままの形でデータベースの XML 列に保管されます。XML 列をサポートするデータベースには、Apache Derby、IBM DB2®、Oracle Database、Microsoft® SQLServer などがあります。

データを中間層からデータベースに渡すのも以前は困難でした。JDBC 4.0 がリリースされる前は、String または CLOB データ型を使用するしか選択肢はありませんでしたが、前述のとおり、これらの型を使用する場合にはデータをシリアライズしなければならないことから、パフォーマンスに問題が生じます。さらに大抵は、データを XML 列に構文解析する方法を認識するために標準外の SQL 拡張が必要になります。そこで JDBC 4.0 で導入されたのが、SQLXML 型の標準サポートです。このサポートにより、データベースに対する XML データの読み取り/書き込み操作を XML 形式のまま行えるようになりました。JDBC 4.0 では、ストリング、読み取り/書き込みストリーム、あるいは JAXP のソースおよび結果から XML データにアクセスすることができます。JDBC 4.0 のこのサポートが意味することは、データベースと中間層両方での余計なマッピングやパフォーマンスのオーバーヘッドに煩わされることなく、中間層およびデータベースで XML をネイティブに受け渡しできるということです。

JDBC 4.0 を使用して XML データにアクセスする単純な例

ここで、JDBC 4.0 サポートの使用例を紹介します。JDBC 4.0 での XML データの読み取りは、他のデータ型を読み取る場合と同様です。

XML データを読み取る基本的な手順は以下のとおりです。

  1. プリペアード・ステートメント (PreparedStatement) を作成します。
  2. プリペアード・ステートメントを実行して結果セットを取得します。
  3. 結果セットから SQLXML オブジェクトを取得します。
  4. サポートされている get メソッドのいずれかを使用して SQLXML オブジェクトを読み取ります。
  5. SQLXML オブジェクトを解放します。

以下に示すのは、極めて基本的な例です。


リスト 2. JDBC 4.0 による XML データの読み取り

PreparedStatement ps =
        dbConnection.prepareStatement("SELECT somexmlcolumn FROM somexmltable");

ResultSet result = ps.executeQuery();

result.next();

SQLXML xml = result.getSQLXML("somexmlcolumn");

StreamSource source = xml.getSource(StreamSource.class);

// Read from the stream source

xml.free();

上記の例では、JAXP ソース・オブジェクトを使用してソースを読み取ります。具体的には、StreamSource というソース・オブジェクトです。このソース・オブジェクトを使うことで、JAXP ソースを認識するあらゆる API がデータを読み取ることができます。StreamSource ソースでは、任意のメモリー内表現を使用することができます。一般に、オブジェクトと API 呼び出しのオーバーヘッドを伴う DOM や SAX などのソースに比べると、ストリームを使うのが最も効率的です。

JDBC 4.0 で XML データを書き込む手順も同様です。

  1. プリペアード・ステートメントを作成します。
  2. データベースへの接続オブジェクトから SQLXML オブジェクトを作成します。
  3. サポートされている set メソッドのいずれかを使用して SQLXML オブジェクトにアクセスします。
  4. SQLXML オブジェクトをプリペアード・ステートメントのパラメーターに設定します。
  5. SQLXML オブジェクトのアクセス・メソッドに書き込みます。
  6. プリペアード・ステートメントを実行します。
  7. SQLXML オブジェクトを解放します。

以下に、ごく基本的な例を記載します。


リスト 3. JDBC 4.0 による XML データの書き込み

PreparedStatement ps = dbConnection.prepareStatement(
        "UPDATE somexmltable SET somexmlcolumn = ?");

SQLXML xml = dbConnection.createSQLXML();

StreamResult result = new StreamResult(xml.setBinaryStream());

ps.setSQLXML(1, xml);

// Write to the stream result

ps.executeUpdate();

xml.free();

中間層

以上の説明のとおり、(CLOB を使用したり、リレーショナル・データにシュレッドしたりするのではなく) XML データベースを使用する価値は、パフォーマンスの向上、XML への忠実性、そして開発の単純化にあります。パフォーマンスが向上する理由は、データを単一の形式で保持することができるからです。異なるデータ・モデルにデータをコピーしなければならないとなると、最悪の場合、さらに余計なシリアライズと構文解析が必要になることもあります。XML への忠実性とは、XML データを保持するためにリレーショナル・テーブルを使用し、そのリレーショナル・テーブルから大体の形で XML データを再現するのではなく、XML データがそのまま形でデータベースに保持されることを意味します。開発については、リレーショナル・データから XML データへのマッピング・コードが一切必要ないことから単純化されます。

ここで、今度は中間層について考えてみましょう。中間層で XML をネイティブに使うことによって、上述の利点は中間層だけでなく、中間層とデータベースの両方にもたらされます。さらに、中間層が接続するソースは XML データベースよりも多いことから、その価値は Web サービス・フィードなどの他の XML データ・ソースにまで拡大されます。

データベース (または他の XML データ・ソース) と中間層の間でデータのコピーが行われないということは、エンド・ツー・エンドのパフォーマンスが向上するということです。さらに、それぞれの層がメモリー内に最もパフォーマンスに優れた XML 表現を作成しながらも、そのデータ表現をベースとした W3C 標準プログラミング・モデルを提供できることから、各層でのパフォーマンスも向上します。

さらに、忠実性も維持されます。この単純な例では、XML への忠実性は些細な問題かもしれませんが、納税申告書などの複雑な XML 文書や、財務報告といった極めて重要な XML 文書を交換する場合を考えてみてください。すべての処理フレームワークで XML データが XML 本来の形を維持することがいかに重要であるかがわかるはずです。

その他のフレームワーク

JDBC をベースに作成された他のパーシスタンス・フレームワークも、データベース内の XML データを何らかの形でサポートします。通常、その手段は XML データをオブジェクト表現にマッピングするというものです。歴史的に見て、パーシスタンス・フレームワークには「アプリケーションを実装する最善の方法とは」で説明したパフォーマンスの問題とリレーショナル・テーブルへのマッピングに関する問題がありました。これらの問題は XML 列と JDBC 4.0 の SQLXML によって解決されましたが、それでもまだ、XML データをネイティブに扱うとなると問題が残ります。問題のひとつは、パーシスタンス・フレームワークは一般に XML データをオブジェクト表現にマッピングしますが、このようなマッピングは、ユーザーが XML データをネイティブに操作したいという場合には不要であることです。そしてもうひとつの問題は、XML データがオブジェクトにマッピングされてしまうと、XML を中心としたナビゲーション、変換、あるいはクエリーは実行できなくなることです。

もう 1 つの利点である開発の単純化は、ある一定の XML プログラミング・モデルのすべてで単一のデータ・モデルを使用することによって実現されます。中間層の Java™ プログラマーにとっては、単純なシナリオではオブジェクトを DOM や JAXB にマッピングしたほうが簡単かもしれませんが、前述の納税申告書の XML 文書となると、単純なシナリオにはなりません。さらに、ユーザーは JDBC と XML だけでなく、他の XML プログラミング・モデルとクエリー・モデルも学ばなければならなくなります。しかし XML データの操作をする際にコレクションと結果を使うようにすることで、プログラマーは XML データ・モデルと W3C 標準さえ知っていれば、XML データのナビゲートや変換、さらには XML データに対してクエリーを実行することもできます。しかも XML データベース内で XPath と XQuery を使用してナビゲートおよびクエリーを行っているとしたら、XML データ・モデルと W3C 標準の知識はおそらくすでにあるはずです。

この開発の単純化を実現する上で最も容易な方法は、データ・ソースからデータを取得して操作し、データベースに結果を格納するという下位レベルの作業の大部分を処理し、しかもコピー操作によるオーバーヘッドのないフレームワークを使用することです。そのようなフレームワークとして、このサンプル・アプリケーションでは IBM WebSphere Application Server V7.0 Feature Pack for XML を使用します。この XML フィーチャー・パックはデータベースの XML データを XML 形式のまま処理できるため、余計なパフォーマンスのオーバーヘッドがありません。また、データが XML 形式のままであれば、XML フィーチャー・パックでは簡単にそのデータのナビゲートや変換、さらにはそのデータに対するクエリーを実行することができます。

IBM WebSphere Application Server V7.0 Feature Pack for XML

IBM WebSphere Application Server V7.0 Feature Pack for XML は、W3C 標準である XPath 2.0、XSLT 2.0、および XQuery 1.0 のプログラミング・モデルを使用して中間層でネイティブ XML のナビゲートや変換、およびネイティブ XML に対してクエリーを実行するためのサポートを導入しています。データベース層で XML データがよく使われているという前提で、これから説明するシナリオでは、製品に依存しない前述の JDBC 4.0 の手法を XML フィーチャー・パックに適用し、データベースには pureXML® の機能を備えた IBM DB2 や Apache Derby、または Oracle Database などの XML データベースを使用することにします。この場合の基本的な接続形態を以下に示します。


図 2. XML フィーチャー・パックと XML データベースの単純な接続形態
XML フィーチャー・パックとネットワークおよび XML データベースの単純な接続形態

この接続形態で、XML データベース、JDBC 4.0 の SQLXML、および XML フィーチャー・パックがデータベースと中間層の XML データをサポートする仕組みを説明します。

このシナリオは XML フィーチャー・パックにサンプル・アプリケーションとしてソース・コードが提供されているので、独自のアプリケーションでシナリオに従ってコードを試してみることができます。XML フィーチャー・パック、Derby、ならびに DB2 Express のダウンロード・リンクは、「参考文献」に記載されています。

データベースのネイティブ XML サポート、JDBC 4.0、XML フィーチャー・パックを組み合わせることによって、単純かつパフォーマンスに優れたアーキテクチャーを実現することができます。

サンプル・アプリケーションの実装

ここからは、XML フィーチャー・パック、JDBC 4.0、および XML データベースを使用してサンプル・アプケーションを実装する方法を説明していきます。このサンプル・アプリケーションはまず初めに、Atom フィードを返すブログ用 Web サービス (図 1 を参照) を使用して、問題のあるコメントをブログから取得します。取得したコメントを処理する際に、データベースの履歴情報をチェックし、そのコメントが過去の不良ブロガー (スパマー) から送信されたものであるかどうかを調べます。この全過程を通して、データは XML 形式のままです。まずは、Atom フィードからブログのコメントに関する情報を取得するところから取り掛かります。

XML フィーチャー・パック内で、Atom フィードからのデータが HTTP 接続を介してブログ用 Web サービスにロードされ、XQuery プログラムへの入力文書として使用されます。XQuery プログラムは XML フィーチャー・パック・ランタイムで実行されます。ランタイムを起動するには、XML フィーチャー・パック Java API を使用します。

Atom フィードから問題のあるコメントを取得するには、XQuery プログラムで以下の XPath 文を使用します。


リスト 4. XPath 文

declare variable $comments := (
  /atom:feed/atom:entry[atom:author/atom:name = 'Anonymous'] |
  /atom:feed/atom:entry[matches(atom:content, $my:vulgarwords, 'i')])
  [atom:published > current-dateTime() - $my:monthsAgo];

XPath を使用して、匿名ユーザーからのコメント、または低俗な言葉が含まれるコメントを、ユーザーが定義した時間枠内を範囲として検索します。これらの基準と一致するすべてのエントリーを comments 変数に格納します。

今度は XQuery を使用して、検出されたスパマーが、スパマーとしてすでにデータベースに登録されているかどうかを調べます ($i は、上記のコメントのサブクエリーです)。


リスト 5. XQuery 文

let $spammedbefore := local:hasEmailHasSpammedBefore($i/atom:author/atom:email/text())

データベースから XML データをロードする方法は、この関数の定義を見るとわかります。


リスト 6. XQuery 関数

declare function local:hasEmailHasSpammedBefore($emailaddress) as xs:boolean {

let $domainName := substring-after($emailaddress, '@')

return
  if ($domainName = '') then
    false()
  else
    let $jdbcURI := concat('jdbc://getAuthorsWhoHaveSpammedFromDomain?', $domainName)
    let $domainSpammers := collection($jdbcURI)
    return
      not(empty($domainSpammers/spammers/spammer/email[. eq $emailaddress]))
};

E メール・アドレスからドメイン・ネームを取得して、その値を名前付きクエリーの jdbc://getAuthorsWhoHaveSpammedFromDomain に連結します。その結果、XPath 2.0 コレクションの URI は jdbc://getAuthorsWhoHaveSpammedFromDomain?DOMAINNAME となります。

XPath 2.0 コレクションは、XQuery または XSLT プログラムのメインの入力文書からは提供されない XML データのシーケンスを容易に統合する手段となります。コレクション関数の実装は、その定義に依存した実装であるため、各 XPath 2.0 ランタイムがそれぞれに固有のデフォルト・コレクション・リゾルバーを提供することも、ユーザーがランタイムを拡張してコレクション実装を動的に提供することもできます。XML フィーチャー・パック・ランタイムでは、ユーザーが XCollectionResolver インターフェースを使って独自のコレクション実装を提供できるようになっています。

このサンプル・アプリケーションに実装した XCollectionResolver は、jdbc:// という URI スキームで始まるすべてのコレクションを処理し、URI の残りの部分を前に定義した一連の名前付きクエリーと突き合わせて解決します。このコレクション・リゾルバーはユーザーによって指定された名前付きクエリーを検索し、位置パラメーターを追加した後、データベースに対して JDBC ステートメントを実行します。

リスト 7 を見ると、基本的な名前付きクエリーを定義した後、どこでこのリゾルバーをインスタンス化しているかがわかります。さらに、リゾルバーにはデータベース接続も渡しているため、リゾルバーはあらゆる JDBC 接続に対して機能します。


リスト 7. リゾルバーの構成

dbStatementsSupportsSQLXML = new HashMap<String, String>();

dbStatementsSupportsSQLXML.put("getAuthorsWhoHaveSpammedFromDomain",
        "SELECT CONTACTS from SPAMMERS where DOMAINNAME = ?");

dbStatementsSupportsSQLXML.put("updateAuthorsWhoHaveSpammedByDomain",
        "UPDATE SPAMMERS SET CONTACTS = ? WHERE DOMAINNAME = ?");

dbStatementsSupportsSQLXML.put("insertAuthorsWhoHaveSpammedByDomain",
        "INSERT INTO SPAMMERS (CONTACTS, DOMAINNAME) VALUES (?, ?)");

Connection conn = getDatabaseConnection();

JDBCCollectionResolver inputResolver =
  new JDBCCollectionResolver(conn, dbStatementsSupportsSQLXML);

リスト 8 に、リゾルバー実装の一部を記載します。完全な実装については、XML フィーチャー・パックのサンプル・ソース・コードを参照してください。このリゾルバーは基本的に、前に記載した JDBC 4.0 で XML データを読み取る単純な例が多少複雑になっているだけです。

このリゾルバーには、再利用しやすくするために以下の変更内容が追加されています。

  1. SQL 文を直接ハードコーディングする代わりに、外部で提供された名前付きクエリーを検索します。
  2. 返された行と列でメタデータの型を調べ、SQLXML 型のXML 列だけを読み取るようにしています。
  3. JDBC クエリーから返された XML データのシーケンスを作成するために、XML フィーチャー・パック API の構成体を 2 つ追加して使用しています (XSequenceCursor および XItemView)。

リスト 8. リゾルバーの実装

public XSequenceCursor getCollection(String uri, String base) {
        // look up query from query collection provided from Listing 7
        String query = lookupNamedQuery(uri);
        PreparedStatement p = dbConnection.prepareStatement(query);
        ResultSet rs = p.executeQuery();
        ...

        // Loop through the result returned from the query
        ResultSetMetaData metadata = rs.getMetaData();
        int colType = metadata.getColumnType(jj+1);
        if (colType = Types.SQLXML) {
                SQLXML sqlx = rs.getSQLXML(...);
                StreamSource source = sqlx.getSource(StreamSource.class);
                XItemView item = itemFactory.item(source);
                sqlx.free();
        }

        // Use the XML Feature Pack API to create a sequence from the returned XML data
        ...
        XItemView itemView[] = items.toArray(new XItemView[0]);
        XSequenceCursor sequence = itemFact.sequence(itemView);

        return sequence;
}

上記のように変更したことにより、XQuery プログラムで使用するコレクション・リゾルバーは、任意の数の入力を受け入れ、XPath 2.0、XSLT 2.0、または XQuery 1.0 で処理する XML データのコレクションを返すという、かなり一般的なものとなりました。ここで、さらに 2 つのサンプル・コードを記載します。最初のコードでは name 要素を使ってすべてのスパマーのリストを作成し、その次のコードで、投稿数が 10 件を超えるスパマーの数を返します。


リスト 9. XQuery の例

Java:
  dbStatementsSupportsSQLXML.put("getAllSpammers", "SELECT CONTACTS from SPAMMERS");
XQuery:
  let $allSpammers := collection('jdbc://getAllSpammers')
  return
    for $i in $allspammers
    let $first := $i/name/first
    order by $i/name/last
    return
      <name>
        <first>{ $first }</first>
        <last>{ $i/name/last }</last>
      </name>

Java:
  dbStatementsSupportsSQLXML.put("getAllSpamAuthorsWhereSpamCountGreaterThan",
    "SELECT CONTACTS from SPAMMERS where COUNT > ?");
XQuery:
  let $minCount := 10
  let $allSpammers := collection(concat(
    'jdbc:// getAllSpamAuthorsWhereSpamCountGreaterThan?',
    $minCount)
  )
  return
    count($allSpammers)
}

コレクション・リゾルバーは XPath 2.0 の一部であることから、XQuery 1.0 だけでなく、XSLT 2.0 にも同じく役立ちます。以下は、コレクション・リゾルバーを使用した単純な XSLT 2.0 の例です。


リスト 10. XSLT の例

<xsl:variable name="allSpammers" select="collection('jdbc://getAllSpammers')"/>

<xsl:template match="/">
        <p>The current spammer database contains the following domains and spammers.</p>
        <xsl:for-each select="$allSpammers">

        <table>
        <tr>
                <th>Name</th><th>Email</th>
        </tr>
        <xsl:for-each select="$allSpammers">
        <tr>
                <td><xsl:value-of select="name"/></td>
                <td><xsl:value-of select="email"/></td>
        </tr>
        </xsl:for-each>
        </table>
</xsl:template>

同様に、データを XML データベースに書き込むことも可能です。XSLT 2.0 では、xsl:result-document 命令を使用して、URI で識別された複数の文書に結果を書き込むことができます。前と同じく、この URI の解決はランタイム実装に依存します。XML フィーチャー・パックでは、ユーザーが結果の書き込み先を指定できるように XResultsResolver インターフェースを提供しています。サンプル・アプリケーションには、これと同じような JDBC 結果リゾルバーを実装しました。この結果リゾルバーは、名前を付けたステートメントと位置パラメーターを使用し、XML パラメーターで —XML— の番兵値を示します。

この結果リゾルバーによって、リスト 11 に示すようにデータベースにデータを書き込むことができます。


リスト 11. XSLT の結果文書

<!--  Is this an insert or an update -->

<xsl:variable name="insert" select="count($spammersByDomain/spammers/spammer) eq 0"/>

<!-- Create the insert statement named query -->

<xsl:variable name="insertJdbcURI"
        select="concat('jdbc://insertAuthorsWhoHaveSpammedByDomain?--XML--&', $domain)"/>

<!-- Create the update statement named query -->

<xsl:variable name="updateJdbcURI"
        select="concat('jdbc://updateAuthorsWhoHaveSpammedByDomain?--XML--&', $domain)"/>

<!—
If insert, insert the xmldoc into the database.
Otherwise, update the database with the xmldoc.
 -->

<xsl:template match="/">
        <xsl:when test="$insert">
                <xsl:result-document href="{$insertJdbcURI}" method="xml" indent="yes"> 
                        <xsl:copy-of select="$xmldoc"/>
                </xsl:result-document>
        </xsl:when>
        <xsl:otherwise>
                <xsl:result-document href="{$updateJdbcURI}" method="xml" indent="yes">
                        <xsl:copy-of select="$xmldoc"/>
                </xsl:result-document>
        </xsl:otherwise>
</xsl:template>

スパマーが新参者の場合 (スパマーが特定のドメインに存在しない場合)、上記のコードを実行すると xsl:when 命令の insert パスが実行されます。この場合、XML ランタイムは xmldoc 変数の内容を以下の結果 URI に書き込むように要求されます。


リスト 12. 結果 URI

jdbc://insertAuthorsWhoHaveSpammedByDomain?--XML--&domain.com

サンプル・アプリケーションの結果リゾルバーは、この文を、以下のように事前定義した名前付きクエリーに解決します。


リスト 13. 名前付きクエリー

INSERT INTO SPAMMERS (CONTACTS, DOMAINNAME) VALUES (?, ?)

続いて、結果リゾルバーは xmldoc 変数の XML コンテンツを最初の位置パラメーターに追加し、domain.com を 2 番目の位置パラメーターに挿入します。

コレクションで XML データを読み取る場合と同じく、結果で XML データを書き込むという操作は、特定の XML 言語に固有の操作ではありません。前の書き込みの例では、XSLT を例として使用しましたが (リスト 11 を参照)、これと同じ結果リゾルバーの手法を使って、XQuery 1.0 プログラムに出力を XML データベースに書き込むように指示することもできます。

汎用 JDBC リゾルバーを使用する場合と他の手法を使用する場合についての注意

この記事では、XML フィーチャー・パックに JDBC 4.0 で実装した JDBC 入出力コレクション・リゾルバーと結果リゾルバーを定義するという手法を説明しましたが、自然でパフォーマンスに優れた XML フィーチャー・パックと XML データベースの統合手法は他にもあります。

例えば入力 (コレクション・リゾルバー) を、ユーザーが定義する具体的な XPath 2.0 拡張関数として、以下のように実装するという方法もあります。


リスト 14. より具体的な XQuery 関数

declare function local:hasEmailHasSpammedBefore($emailaddress) as xs:boolean {

let $domainName := substring-after($emailaddress, '@')

return
  if ($domainName = '') then
    false()
  else
    let $domainSpammers := my:getAuthorsWhoHaveSpammerFromDomain($domainName)
      return
        not(empty($domainSpammers/spammers/spammer/email[. eq $emailaddress]))
};

この手法には、入力と出力がより厳密に定義されるという利点があります。その一方、この手法の欠点は、(考えられるすべてのクエリーに共通の 1 つの関数を作成するのではなく) クエリーの 1 つひとつに拡張関数を作成しなければならないこと、そして入力にしか機能しないことです (いかなる場合でも、出力に対して拡張関数を作成するのは不自然なことであり、不可能なことです)。より一般的なコレクションおよび結果リゾルバーの手法を使用することで、一貫した自然な方法でほとんどの場合に対処することができます。

注意する点として、この記事で説明したコレクション・リゾルバーと結果リゾルバーは、XML フィーチャー・パックのサンプル・コードの一部であり、ここに記載したコードはサンプルです。コードを本番アプリケーションで使用する場合には、アプリケーションのニーズに応じてサンプル・コードを拡張してください。

この記事の XML プログラムは、記事の内容を理解しやすいように意図的に単純にしてあります。参考までに、このサンプル・プログラムは XML フィーチャー・パックのサンプル・コードを使って実行することができます。サンプル・コードには、すべてのソース・コードが (完全な形で) 含まれています。

まとめ

XML データについての歴史的な概略の説明で述べたように、(CLOB を使用したり、リレーショナル・データにシュレッドしたりするのではなく) XML データベースを使用する価値は、パフォーマンスの向上、XML への忠実性、そして開発の単純化にあります。パフォーマンスが向上する理由は、データを単一の形式で保持できるからです。異なるデータ・モデルにデータをコピーしなければならないとなると、最悪の場合、さらに余計なシリアライズと構文解析が必要になることもあります。XML への忠実性とは、XML データを保持するためにリレーショナル・テーブルを使用し、そのリレーショナル・テーブルから大体の形で XML データを再現するのではなく、XML データがそのまま形でデータベースに保持されることを意味します。開発については、リレーショナル・データから XML データへのマッピング・コードが一切必要ないことから単純化されます。

中間層で (XML フィーチャー・パックを使用して) XML をネイティブに扱えるようにすることによって、上述の利点は中間層だけでなく、中間層とデータベースの両方にもたらされます。さらに、中間層が接続するソースは XML データベースよりも多いことから、その価値を Web サービス・フィードなどの他の XML データ・ソースにまで拡大することができます。


参考文献

学ぶために

製品や技術を入手するために

  • この記事のサンプル Web アプリケーションを構築するには、以下のソフトウェアをダウンロードしてください。
    • WebSphere Application Server V7.0 Feature Pack for XML: 更新された XML プログラミング・モデル標準が開発者の生産性を向上させ、新しいアプリケーション開発シナリオに対処します。
    • DB2 Express-C: 柔軟で充実した機能を備えたリレーショナル・データ・サーバー兼 XML データ・サーバーです。
    • Apache Derby: 完全に Java 技術で実装されたオープンソースのリレーショナル・データベースです。

  • IBM 製品の評価版: DB2®、Lotus®、Rational®、Tivoli®、および WebSphere® のアプリケーション開発ツールとミドルウェア製品を体験するには、評価版をダウンロードするか、IBM SOA Sandbox のオンライン試用版を試してみてください。

議論するために

著者について

Photo of Andrew Spyker

Andrew Spyker は WebSphere Application Server 開発チームの STSM (Senior Technical Staff Member) として、3 つの主要な分野に取り組んでいます。まず 1 つはパフォーマンスの分野で、WebSphere Application Server パフォーマンス・チームのリーダーとしての 5 年間の経験を生かし、パフォーマンス・チームのアドバイザー役を務めています。また、SOA ランタイム・アーキテクトとして、特にベンチマーク・ストラテジー、パフォーマンス、XML 整合性を重点に WebSphere SOA ランタイム全体での操作の一貫性を担当しています。そして 3 つ目の分野として最も時間をかけているのが、WebSphere ポートフォリオの XML ストラテジーの考案および促進です。最近では、WebSphere Application Server XML フィーチャー・パックのチーフ・アーキテクトを務めました。

Photo of Bert Van Der Linden

Bert Van Der Linden は 2001 年に IBM に入社し、最終的に 2006 年の DB2 9 リリースへと発展した DB2 pureXML の設計に携わりました。それと並行して多くの顧客とパートナーと交渉し、データベースにおける XML を説得してきました。その活動は、今でも積極的に続けています。IBM に入社する前に勤めていた新興企業、Propel では、スケーラブルな e-commerce アプリケーションをホストする無停止分散ミドルウェアの設計および実装にリーダーとして携わっていました。それ以前は長年 Tandem Computers に勤め、金融業界での多数の重大なアプリケーションを実行するデータベース、NonStop SQL に取り組んできました。

不正使用の報告のヘルプ

不正使用の報告

ありがとうございます。 このエントリーは、モデレーターの注目フラグが設定されました。


不正使用の報告のヘルプ

不正使用の報告

不正使用の報告の送信に失敗しました。


developerWorks: サイン・イン


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。 プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。 お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

表示名をお選びください

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

(半角英数字で3文字以上31文字以下にする必要があります)


「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


この記事を評価する

コメント

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML, Information Management, WebSphere
ArticleID=485251
ArticleTitle=多層にわたる XML のプログラミング: パフォーマンス、忠実性、そして開発の単純化のために中間層で XML を使用する
publish-date=03312010
author1-email=aspyker@us.ibm.com
author1-email-cc=
author2-email=robbert@us.ibm.com
author2-email-cc=

タグ

Help
このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。

スライダーバーを使用することで、より多く(少なく)タグを表示します。

人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。

マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。

このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。