GData APIでスプレッドシートの排他制御とバッチ処理Spreadsheets Data APIを使うための基礎知識(3)(3/3 ページ)

» 2010年06月04日 00時00分 公開
[能登諭株式会社トップゲート]
前のページへ 1|2|3       

複数の処理をまとめてサーバに送信「バッチリクエスト」

 Spreadsheets APIを利用してある程度まとまった量のデータを更新しようとすると、その処理時間の長さが問題になる場合もあると思います。これは、1つ1つの検索や更新処理ごとに、クライアントからサーバに対して通信を行っているためです。

 そのためGData APIでは、複数の処理をまとめてサーバに送信する「バッチリクエスト」が用意されています。バッチリクエストはリソースごとに利用可否が存在し、Spreadsheets APIではセルに対して利用できます。

 ここでは、セル更新を行う際にバッチリクエストを利用する方法について紹介します。バッチリクエストの詳細は「Batch Processing in the Google Data Protocol」を参照してください。

 セル更新をバッチリクエストで行う方法は、ドキュメントの「Updating multiple cells with a batch request」に記述されています。

現状はバッチリクエスト全体を強制更新する形でしか利用できない

 ただし、Spreadsheetsサービス側にバグ「Issue 103: getting If-Match or If-None-Match header required (on batch update)」があるため、If-Matchヘッダに"*"を設定しないと動作しません。そのため、本来はセル単位での更新結果の可否を判定できる仕組みがあるのですが、現状はバッチリクエスト全体を強制更新する形でしか利用できません。

排他制御抜きでバッチリクエストを利用するには

 とはいえ、排他制御抜きでもバッチリクエストを利用したいケースもあるとは思いますので、その方法について紹介します。以下BatchUpdate.javaを見てください。BatchUpdate.javaは最初に紹介したCellUpdate.javaをバッチリクエストを利用するようにしたものです。

  BatchUpdate.java
package sample3;
 
import java.net.URL;
 
import com.google.gdata.client.spreadsheet.CellQuery;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.data.Link;
import com.google.gdata.data.batch.BatchOperationType;
import com.google.gdata.data.batch.BatchUtils;
import com.google.gdata.data.spreadsheet.CellEntry;
import com.google.gdata.data.spreadsheet.CellFeed;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.WorksheetEntry;
 
public class BatchUpdate {
    public static void main(String[] args) throws Exception {
        // 操作対象のワークシートを取得する。
        SpreadsheetService service = SpreadsheetUtil.getSpreadsheetService();
        SpreadsheetEntry spreadsheetEntry = SpreadsheetUtil.findSpreadsheet(
                service, "セル単位でのデータ操作");
        WorksheetEntry worksheetEntry = spreadsheetEntry.getDefaultWorksheet();
 
        // 更新対象のセルを取得
        CellQuery cellQuery = new CellQuery(worksheetEntry.getCellFeedUrl());
        cellQuery.setRange("A5:C5");
        cellQuery.setReturnEmpty(true); // 空セルも返すようにする
        CellFeed cellFeed = service.query(cellQuery, CellFeed.class);
 
        // 更新
        CellFeed batchFeed = new CellFeed();
        CellEntry cellEntry;
        // A3
        cellEntry = cellFeed.getEntries().get(0);
        cellEntry.changeInputValueLocal("3");
        BatchUtils.setBatchId(cellEntry, cellEntry.getTitle().getPlainText());
        BatchUtils.setBatchOperationType(cellEntry, BatchOperationType.UPDATE);
        batchFeed.getEntries().add(cellEntry);
        // B3
        cellEntry = cellFeed.getEntries().get(1);
        cellEntry.changeInputValueLocal("4");
        BatchUtils.setBatchId(cellEntry, cellEntry.getTitle().getPlainText());
        BatchUtils.setBatchOperationType(cellEntry, BatchOperationType.UPDATE);
        batchFeed.getEntries().add(cellEntry);
        // C3
        cellEntry = cellFeed.getEntries().get(2);
        cellEntry.changeInputValueLocal("=SUM(A5,B5)");
        BatchUtils.setBatchId(cellEntry, cellEntry.getTitle().getPlainText());
        BatchUtils.setBatchOperationType(cellEntry, BatchOperationType.UPDATE);
        batchFeed.getEntries().add(cellEntry);
        // バッチリクエスト発行
        Link batchLink = cellFeed.getLink(Link.Rel.FEED_BATCH, Link.Type.ATOM);
        service.getRequestFactory().setHeader("If-Match", "*");
        service.batch(new URL(batchLink.getHref()), batchFeed);
        service.getRequestFactory().setHeader("If-Match", null);
 
        System.out.println("セルの更新が完了しました。");
    }
}

 バッチリクエストを利用する場合は、バッチリクエスト用のCellFeedを作成し、そのCellFeedに対して更新する各セルのCellEntryを登録しておきます。最後にバッチリクエスト用のURLを作成し、SpreadsheetServiceのbatchメソッドを利用することで、バッチリクエストを発行できます。各セルのCellEntryに対しては、バッチリクエスト用の拡張情報の設定が必要であり、これはBatchUtilsのsetBatchIdメソッドとsetBatchOperationTypeを利用します。

 また、現在はSpreadsheetsサービスにバグがあるため、batchメソッド発行前にIf-Matchヘッダに"*"を指定し、強制更新の設定としています。

バッチリクエストの速さを実感するために

 ちなみにBatchUpdate.javaだと、更新するセルの数が少なすぎて、バッチリクエストでどの程度速くなるか実感がわかないと思います。

 そのため、バッチリクエストで早くなることを実感していただけるようにサンプルを作成しておきました。サンプルのMassUpdateByNormal.javaとMassUpdateByBatch.javaです。どちらも30セルを更新するプログラムで、筆者が試した際はMassUpdateByNormal.javaは10秒程度かかったのに対して、MassUpdateByBatch.javaは1秒程度で処理が完了しました。更新対象のセル数が増えるほど、この差は大きくなります。

 ただしバッチリクエストには、1回のリクエストで送信できるデータ量に1Mbyteの制限があります。そのため、この制限を超えるような場合は分割して処理するようにしてください。

コラム 「スプレッドシートの操作履歴」

Google Docsには、各ドキュメントの操作履歴を残してくれる機能があります。この操作履歴はAPI経由の更新操作も対象としています。そのため、プログラムの実装を間違えて意図しない更新処理を行った際に、操作履歴から復元することもできます。この辺はGoogle Docsのいい所ですね。

なお、リクエストごとに操作履歴を残すため、バッチリクエストの場合は単一の操作履歴となります。


次回は、Documents List Data APIについて

 以下が、今回のポイントです。

  1. セルの更新ではupdateメソッドのみ利用する。insertメソッドやdeleteメソッドを利用してはいけない
  2. GData APIにはETagによる排他制御の仕組みが存在する。ちなみに、数式が入ったセルは計算元となるセルの値が変更されると、ETagの値が変更されるので注意
  3. 一度に大量のセルを更新する際はバッチリクエストを利用を検討する。ただし、Spreadsheetsサービスにバグがあるため強制更新でしか利用できない

 次回は、Spreadsheets APIとセットで利用することが多いDocuments List Data APIについて紹介する予定です。Documents List Data APIを利用することでスプレッドシートを生成できるようになります。

@IT関連記事

Google Apps Marketplace企業向けアプリ出店入門
アプリストアは消費者向けだけじゃない 先日開設された業務アプリのためのストアサービスについて、スクリーンショット付きでアプリの登録の手順や注意点を紹介します
リッチクライアント & 帳票」フォーラム 2010/4/8

XMLを取り込んだ最新Officeフォーマットとは
「Office 2007」よりファイル形式として使われている「Office Open XML」ファイルフォーマットについて、その成り立ちやOpenOfficeとの比較、標準化の流れ、仕様の概要、Excelを例にJavaでOfficeファイルのデータを操作する方法を紹介する特集企画
Java Solution」フォーラム

バッチ処理はJavaでバッチリ?その現状とこれから
安藤幸央のランダウン(37) 基幹システムで多く見られるバッチ処理はJavaでどこまで適用できるのか。Spring Batchを筆頭に数々の製品やオープンソースも紹介しよう
Java Solution」フォーラム 2007/11/14

Java TIPSJavaのタスクを定期的に実行する
バッチ処理でデータベースアクセスを効率化する
Java Solution」フォーラム

Javaバッチ処理は本当に業務で“使える”の?
オープンソースフレームワークを使ってバッチ処理の開発手法やノウハウを学んでいく本連載。バッチ処理を知っている人も知らない人も、業務システムに欠かせないバッチ処理について理解を深めましょう
Java Solution」フォーラム

前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。