目次


多層にわたる XML のプログラミング

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

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

Comments

コンテンツシリーズ

このコンテンツは全#シリーズのパート#です: 多層にわたる XML のプログラミング

このシリーズの続きに乞うご期待。

このコンテンツはシリーズの一部分です:多層にわたる XML のプログラミング

このシリーズの続きに乞うご期待。

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 としてクエリーの対象にすることができません。

もう 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 本来の形を維持することがいかに重要であるかがわかるはずです。

もう 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 フィーチャー・パックとネットワークおよび 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 データ・ソースにまで拡大することができます。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

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