0.環境

[Android] 5.1.1

[Android API] 21

1.準備

  • Androidアプリ開発で、SQLiteのライブラリを使う際にハマった点をメモ。

    まずコンストラクターでDBを使う準備をします。

    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    
    class DatabaseHelper extends SQLiteOpenHelper {
    
        public DatabaseHelper(Context context) {
            super(context, "test.db", null, 1);
    
            //(A)既存のDBを消すには下記コードを使用。
            //context.deleteDatabase("DB name is here.");
        }
        //以下省略
    

    第2引数でDB名を指定するとDBファイルがAndroid端末に作成されます。

    第4引数ではDBバージョンを指定し、DB定義を変える際はこれを1つ上げるようにします。

    (バージョンを下げるとクラッシュするので注意)

    また、開発中にDBを作り直したい場合は、上記(A)で削除しましょう。

2.ハマりポイント - DDL記載箇所

  • このライブラリは主に使うメソッドが2つあり、DBのバージョンによって下記の通り実行タイミングが異なります。

    DBファイルが未作成の場合 : onCreate

    DBファイルが既にある場合(DBバージョン1以上) : onUpgrade

    ミスりやすいのが、DBバージョン2以降は、onCreateとonUpgradeの両方にDDLを書く必要があるという点です。

    下記のようにusersテーブルがDBバージョン2で追加されたとして、もし、onUpgradeだけに書いてしまうと、DBバージョン1のユーザーにとっては問題ないですが、初期インストールの場合はonCreateしか実行されないため、usersテーブルが作られないことになります。

    なので、DBバージョン2以降に追加するDDLはprivateメソッドに書いて、上記の両メソッドから呼ぶようにしたらいいと思います。

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.beginTransaction();
        try {
            //DBバージョン1でcitiesテーブル作成。
            String ddlCities = "CREATE TABLE IF NOT EXISTS cities ("
                            + "city_id INTEGER PRIMARY KEY AUTOINCREMENT"
                            + ", city_name TEXT"
                            + ");";
            db.execSQL(ddlCities);
    
            //DBバージョン2でusersテーブル作成。
            createUsersTable(db);
    
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
        }
    }
    
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.beginTransaction();
        try {
            //DBバージョン2でusersテーブル作成。
            createUsersTable(db);
    
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
        }
    }
    
    private void createUsersTable(SQLiteDatabase db){
        String ddlUsers = "CREATE TABLE IF NOT EXISTS users ("
                + "user_id INTEGER PRIMARY KEY AUTOINCREMENT"
                + ", user_name TEXT NOT NULL"
                + ");";
        db.execSQL(ddlUsers);
    }
    

3.ハマりポイント - 特定のDBバージョンのみで実行するDDL

  • ネットで調べたところ、onUpgrade内ではバージョンによって実行するDDLを管理することになっています。

    イコールを使っている例をいくつか見かけましたが、実運用に入ると都合が悪いケースがあります。

    例えば、アップデートをしばらく保留にしていたユーザーが、DBバージョンを3から5へ一気に上げた場合、newVersion == 4と指定していると、そのDDLが実行されないことになります。

    次のようにDBバージョンを範囲で指定しておけば、上記のケースでも、addColumnAgeは実行されるので問題なしです。

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.beginTransaction();
        try {
            //イコールだと問題あり。
            //if(oldVersion == 3 && newVersion == 4){
            //    addColumnAge(db);
            //}
    
            //DBバージョン4でAgeカラム追加。
            if(oldVersion <= 3 && newVersion >= 4){
                addColumnAge(db);
            }
    
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
        }
    }
    

    また、上記「2.ハマりポイント」とも関係しますが、addColumnAge(db);はonCreate内にも追記します。

    onCreateは DBファイルが未作成の場合 向けなので、oldVersionなどの条件指定は不要です。

関連記事

  • SQLiteを使った開発を楽にするにはこちら