飴屋

Androidアプリメモ/メモ12

データベースの構造を変更する

アプリを改修するにあたって初めてこんな問題が出てきました。データベースに体重を記録するアプリなので、体重と計測日時をデータベースに記録をためていたのですが、今回のバージョンアップで血圧と計測日時もためられるようにしたくなったのです。既存のデータベースがある場合、データ構造を変更する必要がありますし、新規にアプリを使い始めた人には最新の構造のデータベースを用意してあげる必要があります、古いデータベースの人とまだデータベースがない人という2パターンの人を想定しないとならない分、少し複雑になります。

private static class DBOpener extends SQLiteOpenHelper {
DBOpener(Context context) {
super(context,DB.DB_NAME,null,3);
}
...

前に書いたSQLiteOpenHelper を継承したクラスの出だし部分です。コンストラクタは親クラスであるSQLiteOpenHelper にContextとデータベース名と「3」という数字を渡しています。この謎の数字こそがデータベースのバージョン番号です。バージョンはintの数値で管理されているのですね。番号が3ということは何度かバージョンアップしていたのですね。記憶にはありませんが多分、初めての開発にあって、ちょこちょことデータベースの定義を間違えて書き換えていたのだと思います。ということは・・・

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

やはりデータベースをバージョンアップしたとき(onUpgrade)には古いバージョンのテーブルをそっくり捨てて、onCreateを呼び出して新しいテーブルを作り直していますね。最初の開発中はユーザーは自分一人だったのでそれでも問題はありませんでしたが、一度公開してしまうと他のユーザーの大事なデータを消してしまいかねない危険な処理ということになります。

ということでもうちょっとしっかりデータベースのバージョン管理をやった方がよさそうです。

private static class DBOpener extends SQLiteOpenHelper {
// バージョンを一つ上げた
private static final int DB_VERSION = 4;

DBOpener(Context context) {
super(context,DB.DB_NAME,null,DB_VERSION);
}
@Override
public void onCreate(final SQLiteDatabase db) {
try {
// 最新のデータベース構造を定義した(テーブル二つ)
db.execSQL(DBOpener.DB_CREATE);
db.execSQL(DBOpener.DB_CREATE_HEART);
} catch (SQLException e) {
}
}
@Override
public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
// バージョンが上がった時は二つ目のテーブルだけ追加する
if (oldVersion<=3 && newVersion==4) {
db.execSQL(DBOpener.DB_CREATE_HEART);
}
}
...

まず、DB_VERSIONという定数を用意してデータベースのバージョンを見やすくしておきました。
onCreateは新しくアプリをインストールした人向けの処理なので、旧データベースから存在するテーブルAと新規に増えたテーブルBの両方をCREATE文で作成するようにします。
onUpgradeでは3以前の古いバージョンで使われていたテーブルAをそのまま保持して、テーブルBだけCREATE文で新規に作成するようにします。データベースのバージョンが変わった際に、変更前と変更後のバージョン番号がそれぞれoldVersionにnewVersionに引数として渡ってくるので、必要な処理を場合分けして書けるというわけですね。

とはいっても、どのバージョンの時にどんな改定が行われたのか、別途記録をつけておかないとプロジェクトによってはわけがわからなくなりそうです。

バージョン番号改定内容
1-3体重テーブルを追加した
4血圧テーブルを追加した

とりあえず、このアプリの場合はこの程度で十分そうです。ものによってはテーブルの行や列を追加削除したり、データの型がまるっと変わったりすることもあると思うので、データベースのバージョン管理をがっつりやってくれるようなライブラリを作っている人もいそうですね。

メモ一覧

Last-Modified