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を使った開発を楽にするにはこちら