進路どーすっかな
本題
既存のAndroidアプリにデータベースを追加したいわけですが、これから作るならRoomをやっぱ使いたいわけですよ。
でもRoomとSQLite(旧式)が共存してるのなんか気持ち悪いのでめっちゃ面倒くさそうだけどRoomへ移行しようというわけです。
環境
なまえ | あたい |
---|
Android | 11 Beta 2 |
言語 | Kotlin |
やること
SQLite -> Room
ライブラリを入れる
build.gradleを開いて
以下のコードを足します。
ファイルの一番上にapply plugin: 'kotlin-kapt'
を書かないとエラー出ます。
あとついでにコルーチンも入れましょう。無くてもthread {}
使って別スレッドで扱えば使えますがコールバック地獄になるのでやめとこう
なんでコルーチン
RoomはUIスレッドでは使えません。
だからコルーチンが必要だったのですね。
Roomの構成
Roomさんは3つのコンポーネントで成り立ってます。
- RoomDatabase
- データベースの中心的な役割
- 説明がめんどいし何するのかよくわかっていない。
- DAOにはこいつが必要
- Entity
- テーブル。Excelだと一番上の行。
- データベースの中身を定義する(主キーとか)
- DAO
- データベースへアクセスする際に使う関数を定義する
- クエリも入力補助が付いたので間違いが減った(+実行前に間違いが分かるようになってる)
移行する
流石にちょっと怖くね?
Entityを作成する
今回はファイル名をCommentCollectionEntity.kt
とします。
例
SQLiteHelperがこうなっているとして
Entityはこうなります(例がクソわかりにくい。まるで教科書の例題の解き方が参考にならない問題みたい)
Entity書くときに注意しないといけないこと
@Entity(tableName = "")
を書かないとだめ。
CREATE TABLE {ここ}
の値ですね。忘れそう
- カラムと変数名が同じじゃない場合は
@ColumnInfo
を使う
- 実はnullを許容するように書くと移行のときだけ楽になる
Migrationを書く
の工程がほぼなくなり楽になりますが、使うときに毎回nullの可能性がある値を使う羽目になるので今回はnull絶対許さん方針で行きます。
- nullを許容する場合は
String?
やInt?
のように最後に?
をつければいいですが今回はつけません。
DAOを書く
データベースへアクセスするする際に使う関数を定義します。
クエリもここに書きます。
ここでは一般的に使いそうな動作を例として置いとくので、各自Entityクラス名等を書き換えてください。
ファイル名はCommentCollectionDAO.kt
で
これを書く際も入力補助が聞くので間違いが減ります(この記事二回目の発言)
注意点
なくない?
Database
中心的な役割を持ちます。
ファイル名はCommentCollectionDB.kt
で
注意点
データベースへアクセス
データベースを使うときにバージョンを上げる処理を書きます。
まあこれじゃ動かないんですけどね。
そのための addMigrations があるので使っていきます。
なんで?動かないの?
実はEntityでnullを許容すればこの問題は消えます。
しかしnullを許容すると使うときに面倒くさくなります(この例だとcomment?.length
みたいに?付けないといけなくなる)
この問題はSQLiteとRoomとでnullを許すかどうかで問題が発生しています。
- SQLiteくん
- Roomくん
Entity
がnullを許してくれない;;
- よし落とすか←いまここ
ちなみに出力されたエラーはこちら。
よく見ると上のExpected
の方のnotNull
はtrue(null良いよ)
ですが、
Found(今回作ったEntity)
はnotNull
がfalse(nullだめだよ)
ってことで中身が噛み合わず例外が発生しています。
Migration
nullを許容 から nullを許さん に変更したいのですが、残念ながら変更するにはデータベースを作り直す必要があるそうです。
まあまあ面倒くさい。やることは以下の4つ
- 新しくデータベースを作成する
- 新しく作ったデータベースへデータを移す
- 古いデータベースを消す
- 新しく作ったデータベースの名前を古いデータベースの名前に変更する
これをKotlinで書くとこうなります。
全部くっつけるとこう
以上です。
追加する方法
SQLite時代のContentValues
よりずっとわかりやすい。
これ今まで通りSQLiteOpenHelper経由でアクセスするとどうなるの?
バージョン下げんなって怒られた。
おわりに
カラムが縦か横かわからん時がよくあるのでその時はTweetDeckがマルチカラムだってことを思い出してあ~横並びのことか~って思い出すようにしています。
作らないと行けないファイルが多くて初見さんは大変そうだと思った(こなみ)
参考にしました
https://developer.android.com/training/data-storage/room/migrating-db-versions
https://medium.com/@manuelvicnt/android-room-upgrading-alpha-versions-needs-a-migration-with-kotlin-or-nonnull-7a2d140f05b9
https://stackoverflow.com/questions/47562157/android-room-migration-null-error
https://qiita.com/arara_tepi/items/7267418ca4b6bd65d744#notnull%E3%82%92%E5%90%88%E3%82%8F%E3%81%9B%E3%82%8B