Android Kotlin基礎講座 06.1: Roomデータベースを作成する
目次
タスク:DAOを作成する
このタスクでは、データアクセスオブジェクト(DAO)を定義します。Androidにおいて、DAOはデータベースの挿入、削除、更新用の便利なメソッドを提供しています。
Roomデータベースを使う際には、コード内でKotlin関数を定義、呼び出しすることによってデータベースのクエリを行います。これらのKotlin関数はSQLクエリに位置します。DAO内にアノテーションを使って定義し、Roomが必要なコードを作成します。
DAOはデータベースにアクセスするためのカスタムインターフェースの定義と捉えてください。
一般的なデータベースの操作用に、Roomライブラリは@Insert、@Delete、@Updateといった便利なアノテーションを用意しています。その他全てについては、@Queryアノテーションがあります。SQLiteにサポートされているどんなクエリでも書くことができます。
加えて、Android Studioでクエリを作成する際、コンパイラーはSQLクエリに構文エラーがないかまでチェックしてくれます。
sleep-trackerデータベースを扱う上では以下のことができる必要があります。
- 新しい夜を挿入する。
- 既に存在している夜の終了時間と睡眠の質を更新
- 指定した夜をキーをもとにして取得
- 画面に表示するために全ての夜を取得
- 最新の夜を取得
- データベース内の全ての実体を削除
ステップ1:SleepDatabase DAOを作成する
- databaseパッケージのSleepDatabaseDao,ktを開いてください。
- interface SleepDatabaseDaoが@Daoによってアノテーションされていることを確認してください。全てのDAOは@Daoというキーワードでアノテーションされる必要があります。
@Dao
interface SleepDatabaseDao {}
- インターフェースのボディ内に@Insertアノテーションを追加してください。その下にEntityクラスであるSleepNightを引数にとるinsert()関数を追加してください。
これだけです。これでRoomがSleepNightをデータベースに挿入するために必要なコードを全て生成してくれます。Kotlinコードからinsert()を呼び出すと、Roomは実体をデータベースに挿入するためのSQLクエリを実行します。(呼び出したい関数をなんでも呼び出せます)
@Insert
fun insert(night: SleepNight)
- SleepNight用のupdate()関数と@Updateアノテーションを追加してください。更新される実体は渡されたキーと同じキーをもつ実体です。実体の一部、または全てのプロパティを更新することができます。
@Update
fun update(night: SleepNight)
残りの機能には便利なアノテーションがありませんので、@Queryアノテーションを使ってSQLiteクエリを書いてあげる必要があります。
- get()関数と@Queryアノテーションを追加してください。get()関数はLong型のkeyを引数にとり、nullがありえるSleepNightを返します。パラメータに関するエラーが表示されます。
@Query
fun get(key: Long): SleepNight?
- クエリはstring型のパラメータとしてアノテーションに渡されます。@QueryにSQLクエリを表すString型のパラメータを追加してください。
- daily_sleep_quality_tableから全てのカラムを選択します。
- WHEREでnightIdが引数keyに合致した部分を抽出します。
:keyを確認してください。関数の引数を参照させるためにコロンノーテーション(:)を使います。
("SELECT * from daily_sleep_quality_table WHERE nightId = :key")
- さらに@Queryをclear()関数と共に追加してください。daily_sleep_quality_tableから全てのデータを削除するSQLiteクエリを追加してください。このクエリはテーブル自体を削除するものではありません。
@Deleteアノテーションは一つのアイテムを削除します。削除する夜のリストを渡すこともできます。これの欠点はテーブルに何があるのか知ったり、フェッチする必要があることです。@Deleteアノテーションは特定の実体を削除するのには素晴らしい機能ですが、テーブルから全ての実体を削除するのには不向きで、非効率的です。
@Query("DELETE FROM daily_sleep_quality_table")
fun clear()
- さらに@QueryをgetTonight()関数と共に追加してください。この関数ではSleepNightをnull許容で返すようにします。そうすることでテーブルが空の場合でもエラーが起きません。(テーブルは一番初めとデータがクリアされた直後は空になっています)
データベースから”tonight”を取得するために、nightIdを基に降順で並び替えられた結果のリストの最初の要素を返すSQLiteクエリを書いてください。一つだけ要素を返すためにはLIMIT 1を使ってください。
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC LIMIT 1")
fun getTonight(): SleepNight?
- 最後に@QueryをgetAllNights()関数と共に追加してください。
- SQLiteクエリに降順に並べられたdaily_sleep_quality_tableから全てのカラムを返すようにしてください。
- getAllNight()関数はSleepNight実体のリストをLiveDataとして返すようにしてください。RoomはLiveDataを常に更新してくれています。つまり明示的にこのデータを取得するのは一度だけでよいということです。
- androidx.lifecycle.LiveDataからLiveDataをインポートする必要があるかもしれません。
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC")
fun getAllNights(): LiveData<List<SleepNight>>
- ここまででアプリに目に見える変化はないはずです。エラーがないか、アプリを起動して確認してください。