はじめに
とりあえずこれに従えばできるみたいなサンプルを作ろうと思います。
サンプルは次の手順で作成していきたいと思います。
- Room をセットアップする
- Entity(User) を定義する
- Dao(UserDao) を定義する
- RoomDatabase(AppDatabase) クラスを定義する
役割 | クラス名 | 役割 |
---|---|---|
Entity | User | データベースのテーブルを表すクラス |
Data Access Objects | UserDao | データベースにアクセスするメソッドを定義するクラス |
RoomDatabase | AppDatabase | Daoを生成するためのRoomDatabaseを継承した抽象クラス |
0. Roomをセットアップする
次の依存関係を記述し Room をセットアップする。
KTX や Coroutines を利用する場合には room-ktx
を入れます。
Kotlin を利用するならば annotationProcessor
ではなくkapt
を利用するようにします。
apply plugin: 'kotlin-kapt'
dependencies {
def room_version = "2.2.2"
implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.room:room-ktx:$room_version"
kapt "androidx.room:room-compiler:$room_version"
}
1. Entity ( User ) を定義する
データベースにテーブルを表す Entity を定義します。
Entity は @Entity
をクラスに付けるだけで定義できます。
デフォルトだとテーブル名称としてクラス名称が登録されるようになっています。
必要であれば tableName
にてテーブル名称を変更してください。
@Entity(tableName = "users")
data class User(val id: Int, val firstName: String?, val lastName: String?, val age: Int)
Entity には必ず 1つの主キーを指定する必要があります。
主キーは @PrimaryKey
アノテーションをクラスのプロパティにつけるだけで指定します。
また @PrimaryKey
では autoGenerate
にて自動生成するか設定できるようになっています。
なので必要に応じて autoGenerate = true
を付けて、主キーを自動生成するようにして下さい。
@Entity(tableName = "users")
data class User(
@PrimaryKey(autoGenerate = true) val id: Int,
val firstName: String?,
val lastName: String?,
val age: Int
)
デフォルトだとテーブルに登録されるカラム名称はプロパティ名称が登録されるようになっています。
登録されるカラム名称は@ColumnInfo
で変更できるようになっています。
なので必要に応じて @ColumnInfo(name ="xxxxx")
を付けて、カラム名称を変更するようにしてください。
@Entity(tableName = "users")
data class User(
@PrimaryKey(autoGenerate = true) val id: Int,
@ColumnInfo(name = "first_name") val firstName: String?,
@ColumnInfo(name = "last_name") val lastName: String?,
val age: String?
)
デフォルトだと Entity に定義される全てのプロパティをテーブルのカラムとして登録します。
あるプロパティをテーブルに含めたくない場合、@Ignore
を付けることでテーブルに含めないようにできます。
@Entity(tableName = "users")
data class User(
@PrimaryKey(autoGenerate = true) val id: Int,
@ColumnInfo(name = "first_name") val firstName: String?,
@ColumnInfo(name = "last_name") val lastName: String?,
@Ignore val age: String?
) {
// @Ignore を付ける場合は、テーブルに含めるプロパティで初期化するコンストラクタを作成する必要があります。
constructor(id: Int, firstName: String?, lastName: String) : this(id, firstName, lastName, null)
}
2. Dao ( UserDao ) を定義する
データベースにアクセスするクラスである Dao を定義していきます。
Dao は @Dao
をインタフェースに付けるだけで定義できます。
このインタフェースに挿入・削除・更新・取得を行うメソッドを実装していきます。
@Dao
interface UserDao {}
挿入は @Insert
、削除は@Delete
、更新は@Update
を付けて定義します。
このようにアノテーションを定義すれば、あとは Room が勝手に処理を実装してくれます。
@Dao
interface UserDao {
@Insert
fun insert(user : User)
@Update
fun update(user : User)
@Delete
fun delete(user : User)
}
@Query
を付けば自身で記述したクエリを実行できるようにします。
@Query
には引数に指定したパラメータをクエリに含めることもできます。
@Dao
interface UserDao {
@Insert
fun insert(user : User)
@Update
fun update(user : User)
@Delete
fun delete(user : User)
@Query("delete from users")
fun deleteAll()
@Query("select * from users")
fun getAll(): List<User>
@Query("select * from users where id = :id")
fun getUser(id: Int): User
}
3. RoomDatabase ( AppDatabase ) を実装する
RoomDatabase を拡張した抽象クラスである AppDatabase を生成します。
abstract class AppDatabase : RoomDatabase() {}
@Database
を付け、 entities
に 1. で定義した Entity を指定します。
@Database(entities = arrayOf(User::class), version = 1)
abstract class AppDatabase : RoomDatabase() {}
そして 2.で定義した Dao を取得するためのメソッドを用意すれば実装完了です。
@Database(entities = arrayOf(User::class), version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
おわりに
ここまで定義したクラスを利用して処理を記述する次の感じになります。
Room は Main スレッドで実行すると怒られるので、
Coroutine などを利用して Main スレッドで実行しないようにしましょう。
val database =
Room.databaseBuilder(applicationContext, AppDatabase::class.java, "database-name")
.build()
val userDao = database.userDao()
val newUser = User(0, Date().time.toString(), Date().time.toString(), null)
userDao.insert(newUser)
Log.v("TAG", "after insert ${userDao.getAll().toString()}")
V/TAG: after insert [User(id=138, firstName=1579438392369, lastName=1579438392369, age=null)]
V/TAG: after deleteAll []