Room(二)
Query 是 DAO 中使用的主要註解。它允許在資料庫上執行讀/寫操作。每個 @Query
方法都在編譯時被檢查,因此,如果存在查詢問題,則會在編譯時就發生錯誤而不是在 runtime 的時候才被發現,有助於提升 debug 的速度。
1.如果只有一些字串匹配,則發出警告。
2.如果沒有字串匹配,則會報錯。
@Query("SELECT * FROM room_entity")
fun getAll(): List<RoomEntity>
@Query("SELECT * FROM room_entity WHERE name LIKE :name")
fun findByName(name: String): RoomEntity
有些查詢可能要求傳遞一個可變數量的參數,其中參數的確切數目直到運行時才知道。例如,希望從區域的子集檢查有關所有用戶的信息。
@Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
fun loadUsersFromRegionsSync(regions: List<String>): <List<User>>
@Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
fun loadUsersFromRegionsSync(regions: List<String>): LiveData<List<User>>
implementation "androidx.room:room-rxjava2:2.2.4"
庫添加到 gradle 中。 @Query("SELECT * from user where id = :id LIMIT 1")
fun loadUserById(id: Int): Flowable<User>
@Query("SELECT * FROM user WHERE age > :minAge LIMIT 5")
fun loadRawUsersOlderThan(minAge: Int): Cursor
當資料庫已經存在並且被建立時,在不丟失原本資料的前提下,想要添加欄位是很麻煩的一件事情,一不小心就會把舊資料丟失或者蓋掉,甚至是一開啟資料庫就閃退等等的情形。
Room 在這方面也做了優化,使得升級資料庫變的相當容易,直接來看範例:
在已經存過資料的 Entity 添加一個欄位 imageUrl
@Entity(tableName = TABLE_NAME)
class RoomEntity {
...
...
var imageUrl = ""
}
修改 Database
@Database(entities = [(RoomEntity::class)], version = 2)
abstract class RoomDbHelper : RoomDatabase() {
companion object {
@Volatile private var instance: RoomDbHelper? = null
private val LOCK = Any()
operator fun invoke(context: Context)= instance ?: synchronized(LOCK){
instance ?: buildDatabase(context).also { instance = it}
}
private fun buildDatabase(context: Context) = Room.databaseBuilder(context,
RoomDbHelper::class.java, "item-list.db")
.addMigrations(MIGRATION_1_TO_2)
.build()
val MIGRATION_1_TO_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
val tableName = TABLE_NAME
database.execSQL(
"ALTER TABLE $tableName ADD COLUMN imageUrl TEXT NOT NULL DEFAULT ''")
}
}
}
abstract fun getRoomDao(): RoomDao
}
關鍵在這段
val MIGRATION_1_TO_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
val tableName = TABLE_NAME
database.execSQL(
"ALTER TABLE $tableName ADD COLUMN imageUrl TEXT NOT NULL DEFAULT ''")
}
Room 提供了一個類別 Migration
來升級版本,裡面只需要傳入兩個 Int 來表示目前的版本號以及要升級到多少的版本號。
public Migration(int startVersion, int endVersion) {
this.startVersion = startVersion;
this.endVersion = endVersion;
}
(Java source code)
並在覆寫的 migrate
方法裡面把要升級的 Table Name、欄位名稱和欄位型態寫進去。
在 buildDatabase 時添加 addMigrations(MIGRATION_1_TO_2)
private fun buildDatabase(context: Context) = Room.databaseBuilder(context,
RoomDbHelper::class.java, "item-list.db")
.addMigrations(MIGRATION_1_TO_2)
.build()
最後記得在 Database 把版本號修改一下,就成功囉。
@Database(entities = [(RoomEntity::class)], version = 2)
有任何問題或講得不清楚的地方歡迎留言和我討論。
更歡迎留言糾正我任何說錯的地方!