コンピュータクワガタ

かっぱのかっぱによるコンピュータ関連のサイトです

Androidアプリ入門 No.69 SQLiteの使用 SQLiteを使った簡単なアプリ

SQLiteの基本

SQLiteを使った簡単なアプリ

まず、SQLiteを使用した簡単なアプリを作り、どのような作りになるのか確認する。

項目 内容
Project name DbTest
Build Target Android 1.6
Application name DbTest
Package name sample.dt
Create Activity DbTest
Min SDK Version 4

まず、レイアウトのmain.xmlを以下のようにする。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<Button
    android:id="@+id/readButton"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="データ読み込み"
    />
<TextView
    android:id="@+id/resultTextView"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    />
</LinearLayout>

次に、データベースを操作するDatabaseHelper.javaを以下に示す。このクラスは、SQLiteOpenHelperクラスを継承して作成する。

package sample.dt;

import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DatabaseHelper extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "testdb";

    private static final String CREATE_TABLE = "CREATE TABLE emp ("
            + "key INTEGER PRIMARY KEY AUTOINCREMENT," + "name TEXT," + "age INTEGER" + ")";

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

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE);

        insert(db, "エクレア", 21);
        insert(db, "フローズンヨーグルト", 22);
        insert(db, "ハニカム", 30);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS emp");
        onCreate(db);
    }

    public void insert(SQLiteDatabase db, String name, int age) {
        ContentValues cv = new ContentValues();
        cv.put("name", name);
        cv.put("age", age);
        db.insert("emp", "", cv);
    }
}

最後に、DbTest.javaを以下に示す。ボタンを押すとデータベースの内容を読み込み表示する。

package sample.dt;

import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class DbTest extends Activity {
    private Button readButton;
    private TextView resultTextView;
    private DatabaseHelper databaseHelper;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // DB作成
        databaseHelper = new DatabaseHelper(getApplicationContext());

        readButton = (Button) findViewById(R.id.readButton);
        readButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                read();
            }
        });
        resultTextView = (TextView) findViewById(R.id.resultTextView);
    }

    private void read() {
        SQLiteDatabase db = databaseHelper.getReadableDatabase();
        Cursor cursor = db.query("emp", new String[] { "name", "age" }, null, null, null, null,
                null);
        cursor.moveToFirst();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < cursor.getCount(); i++) {
            sb.append(cursor.getString(0)).append(",");
            sb.append(cursor.getInt(1)).append("\n");
            cursor.moveToNext();
        }
        cursor.close();
        resultTextView.setText(sb.toString());
    }
}

実行結果は以下。

ここでデータベース操作の方法を解説する。まず、データベースを操作するためにSQLiteOpenHelperクラスを継承する。継承後にオーバーライドすべきメソッドはonCreateとonUpgradeとなる。まず、onCreateから確認する。onCreateの定義は以下となる。

public abstract void onCreate(SQLiteDatabase db)

引数の詳細は以下。

引数 説明
db データベースのオブジェクト。

onCreateはデータベースを作成する最初だけ呼び出される。通常、このメソッドでdbに対してDDLを発行しテーブルを作成したり、初期データを登録したりする。
次に、onUpgradeメソッドの定義は以下となる。

public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)

引数の詳細は以下。

引数 説明
db データベースのオブジェクト。
oldVersion 古いデータベースのバージョン。
newVersion 新しいデータベースのバージョン。

onUpgradeはデータベースがアップグレードする必要がある場合に呼ばれる。データベースのアップグレードはそれをDROPしたり、新しいテーブルを追加したりするために使用する。今回は、テーブルを再作成しているだけである。
次に、SQLiteDatabaseクラスについて確認する。まずは、execSQLメソッドについて確認する。execSQLメソッドの定義は以下となる。

public void execSQL(String sql)

引数の詳細は以下。

引数 説明
sql 実行するSQL

execSQLは1つのSQLを実行する。SQLは問い合わせ(SELECT文)ではないものが対象となる。今回は、CREATE TABLEとDROP TABLEを実行している。
もうひとつ今回のサンプルで使用しているのは、insertメソッドとなる。insertメソッドの定義は以下となる。

public long insert(String table, String nullColumnHack, ContentValues values)

引数の詳細は以下。

引数 説明
table insertするテーブル名。
nullColumnHack テーブルに値を挿入する際に、valuesが空の場合に使われる。nullColumnHackに指定された列には、明示的にNULLが割り当てられる。
values insertする値。ContentValuesクラスについては後述。

ここでinsertする際に使用したContentValuesについて解説する。ContentValuesは型が決まっているMapのような動きをする。ContentValues#putメソッドを用いてinsertで格納する値を設定する。具体的にputメソッドは以下のような定義になっている。

public void put(String key, 型 value)

引数の詳細は以下。汎用的に使えるが、ここではデータベース操作に使う前提で説明する。

引数 説明
key 列名。
value 列に格納する値。

第2引数の型には、Byte、Short、Integer、Long、Float、Double、Boolean、String、byte[]が入る。型が保証されているため非常に使いやすい。実際に発行されるINSERT文では、keyに指定された列名が自動的にマッピングされINSERT文が作成される。
最後にデータを取得する例を解説する。まず、データベースを操作するためにActivity側でSQLiteDatabaseオブジェクトを取得する。

SQLiteDatabase db = databaseHelper.getReadableDatabase();

その後、そのオブジェクトに対してSELECT文を発行する。今回の例では単純に発行するのではなく、queryメソッドで発行している。queryメソッドの定義は以下のようになる。

public Cursor query(String table, String[] columns, String selection,
String[] selectionArgs, String groupBy, String having, String orderBy)

引数の詳細は以下。

引数 説明
table テーブル名
columns SELECT文の結果取得する列名。
selection WHERE句をWHEREを除いて指定する。
selectionArgs WHERE句で指定された?を置き換える文字列。具体的な例は後述する。
groupBy GROUP BY句をGROUP BYを除いて指定する。
having HAVING句をHAVINGを除いて指定する。
orderBy ORDER BY句をORDER BYを除いて指定する。

queryを指定するとCursorオブジェクトが取得できる。そのCursorを使用してデータを取得する。先ほどの例で実際にCursorを使用している部分を見る。

Cursor cursor = db.query("emp", new String[] { "name", "age" }, null, null, null, null, null);
cursor.moveToFirst();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < cursor.getCount(); i++) {
    sb.append(cursor.getString(0)).append(",");
    sb.append(cursor.getInt(1)).append("\n");
    cursor.moveToNext();
}
cursor.close();

Cursorを取得した後、Cursor#moveToFirst()メソッドで取得した一覧の先頭に移動している。その後、Cursor#getCount()メソッドで取得した一覧の件数を取得している。
その一覧に対して、Cursor#getString(列番号)やCursor#getInt(列番号)メソッドを用いて現在の行の値を列番号で取得する。Cursorはその名前の通り特定の1行を指示しているため、次の行を確認するためにはCursor#moveToNext()メソッドでカーソルの位置を次に移動させる。