連載
» 2009年05月20日 00時00分 公開

Androidで動く携帯Javaアプリ作成入門(6):AndroidでSQLiteのDB操作をするための基礎知識 (2/3)

[緒方聡,株式会社イーフロー]

データベース操作サンプルの画面構成とスキーマ

 今回作成したサンプルは、都道府県データベースアプリケーションです。

図1 都道府県アプリケーション画面 図1 都道府県アプリケーション画面

 都道府県名を変更すると、県庁所在地と郷土料理が切り替わります。都道府県名も県庁所在地も郷土料理名もすべてデータベースから取得しています。データベースのスキーマは以下のようになっています。

図2 データベーススキーマ 図2 データベーススキーマ

 県庁所在地は各都道府県に必ず1つだけ存在するので、プライマリキーを設定しています。郷土料理はいくつ存在するか分からないため、プライマリキーはありません。この2つのテーブルは都道府県でリレーションしています。

 なお、郷土料理が登録されていない県がありますが、あしからずご了承ください。

Androidのデータベースを作成するには?

 スキーマが決まったら、データベースを作成します。

 データベースの作成方法はいろいろありますが、今回は「SQLiteOpenHelper」というクラスを利用します。このクラスは、abstract抽象クラスなので、以下のコールバックを実装する必要があります。

  • public void onCreate(SQLiteDatabase db)
    データベースを作成したタイミングで呼び出される。通常はここでテーブルを作成する。今回はデータもこのタイミングで追加している
  • public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
    データベースをバージョンアップしたタイミングで呼び出される。通常はここでデータのコンバートなどを行う。今回は使用しないので、空実装

 データベースの存在チェックやテーブルの作成、初期データの追加、データベースのバージョンアップ時の処理などが、このクラスを使用することで分離できるので、SQLiteDatabaseクラスでデータベースを直接作成するよりも便利だと思います。

トランザクションとプリコンパイルステートメントとは?

 テーブルにレコードを追加する場合、通常は1レコードずつ追加しなければなりません。これを素直に実装すると、以下のようになります。

for (String s : array) {
    db.execSQL(“insert into table values (‘” + s + “’);”);
}

 1レコードを追加する場合であれば、この方法で十分ですが、複数レコードを追加するのであれば、以下のようにトランザクションプリコンパイルステートメントを使うことを推奨します。

db.beginTransaction();
try {
    SQLiteStatement stmt = db.compileStatement("insert into table values (?);");
    for (String s : array) {
        stmt.bindString(1, s);
        stmt.executeInsert();
    }
    db.setTransactionSuccessful();
} finally {
    db.endTransaction();
}

 このコードは前述のexecSQLを単体で実行するのに比べ、以下のメリットがあります。

  • 途中で失敗した場合ロールバックができる
  • 高速

ロールバック

 上記のコードでは、tryブロックの最後のSQLiteDatabase#setTransactionSuccessful()を呼び出すと、データベースへの変更がコミットされ、呼び出さなければロールバックされます。「例外が発生したらロールバックする」という実装ですね。

処理速度

 処理速度にどれぐらいの差異があるのか計ってみました。以下は、今回のサンプルアプリケーションで約190レコードを追加する際にかかった時間です。

SQLiteDatabase#execSQL(String) トランザクション+SQLiteStatement
1回目 871ms 462ms
2回目 925ms 488ms
3回目 860ms 540ms
4回目 1111ms 510ms
5回目 948ms 498ms
平均 943ms 500ms
表1 処理速度の比較

 トランザクション+SQLiteStatemenの方がおよそ半分の時間で済んでいます。レコード数が増えれば増えるほど、この差はどんどん大きくなります。

データベースの保存場所はメモリ? ストレージ?

 SQLiteはクライアント・サーバ型のデータベースとは異なり、アプリケーションに組み込んで使用するようにデザインされています。AndroidのSQLiteの場合、データベースはデータベースを作成したアプリケーション専用です。

 さらにAndroidの場合、データベースの作成場所をストレージにするか、メモリにするかを選択できます。今回のデモアプリはデータが少ないので、メモリ上にデータベースを作成しています。

データベースの保存場所を指定するには?

 ストレージに作成するかメモリに作成するかは、DatabaseHelperクラスのコンストラクタの第2引数で指定します。

public DatabaseHelper(Context context) {
    super(context, null, null, 1);
}

 ここがnullならメモリ上に、ファイル名を指定した場合は「/data/data/<パッケージ名>/database/<ファイル名>」に、という具合にデータベースファイルが作成されます。指定するのはファイル名だけなので、間違えないようにしてください。

データベースの存在チェックは不要

 ファイル名を指定した場合は、2回目以降の起動でデータベースがすでに存在する可能性があるのですが、もし存在するならDatabaseHelper#onCreate(SQLiteDatabase)メソッドは呼び出されません。DatabaseHelperを使用すれば、データベースの存在チェックを行わなくてもよいわけです。本当に便利です。

 次ページでは、データベースを削除する際の注意点やデータ検索の仕方の基本を解説します。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

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

メールマガジン登録

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