Room的一次實踐

寫在前面

最近在看Room,這裏簡單記錄一下,方便以後回顧學習,理論就不說了,理論知識這裏自行了解。

準備工作

  • 環境配置

    room_version = “2.2.0-alpha01”

    implementation “androidx.room:room-runtime:$room_version”
    kapt “androidx.room:room-compiler: $room_version”
    implementation “androidx.room:room-ktx: $room_version”

  • 基礎結構
    基礎結構
    dao包內存放Dao文件,entity包負責存放實體類,AppDataBase是DataBase的實現類。

建立一個用戶表

這裏我建立一個用戶表,包含以下字段,自增_id,姓名name,年齡age,代碼如下

@Entity
data class User(
    @PrimaryKey(autoGenerate = true) val _id:Int,
    val name:String,
    val age:Int
)

接下來建立一個用戶表的操作類UserDao,代碼如下

@Dao
interface UserDao {
    /**
     * 添加一個用戶
     */
    @Insert
    fun insert(user: User)
    /**
     * 刪除一個用戶
     */
    @Delete
    fun delete(user:User)

    /**
     * 查詢所用用戶
     */
    @Query("select * from User")
    fun queryAll():List<User>
    
}

在DataBase中註冊下

//entities指定表,version指定版本
@Database(entities = arrayOf(User::class),version = 1)
abstract class AppDataBase :RoomDatabase(){

    abstract fun getUserDao():UserDao
 	
 	companion object{
        private var instance:AppDataBase?=null

        fun getInstance(context: Context):AppDataBase{
            if (instance==null){
                synchronized(AppDataBase::class){
                    if (instance==null){
                        instance=Room.databaseBuilder(context,AppDataBase::class.java,"room")
                            .build()
                    }
                }
            }
            return instance!!
        }
    }
 }

相關操作(注:不要在主線程操作,會報錯的!!!

  • 增加一個用戶
AppDataBase.getInstance(this).getUserDao().insert(User(name = "張三",age = 22))
  • 查詢所有用戶
AppDataBase.getInstance(this).getUserDao().queryAll()
  • 刪除一個用戶
AppDataBase.getInstance(this).getUserDao().delete(user)

給用戶表添加愛好(likes)字段

@Entity
@TypeConverters(StringConverter::class)
data class User(
    @PrimaryKey(autoGenerate = true) val _id:Int=0,
    val name:String,
    val age:Int,
    val likes:List<String>?
)

這裏需要用到類型轉換TypeConverters,需要寫一個StringConverter類,具體實現如下

class StringConverter {
    @TypeConverter
    fun listTostring(list:List<String>):String{
        return Gson().toJson(list)
    }

    @TypeConverter
    fun stringTolist(str:String?):List<String>?{
        return Gson().fromJson<List<String>>(str, object : TypeToken<List<String>>() {

        }.type)
    }
}

UserDao中也要添加下@TypeConverters註解

@Dao
@TypeConverters(StringConverter::class)
interface UserDao {
...
}

然後數據庫版本升級

@Database(entities = arrayOf(User::class),version = 2)
abstract class AppDataBase :RoomDatabase(){

    abstract fun getUserDao():UserDao


    companion object{
        private var instance:AppDataBase?=null

        fun getInstance(context: Context):AppDataBase{
            if (instance==null){
                synchronized(AppDataBase::class){
                    if (instance==null){
                        instance=Room.databaseBuilder(context,AppDataBase::class.java,"room")
                            .addMigrations(object :Migration(1,2){
                                override fun migrate(database: SupportSQLiteDatabase) {
                                    database.run {
                                        execSQL("alter table User add COLUMN likes TEXT")
                                    }
                                }

                            })
                            .build()
                    }
                }
            }
            return instance!!
        }

    }
}

小提示:這個是添加的List< String >,你也可以將String替換爲其它類型哦,@TypeConverter與@TypeConverters的使用主要是將數據庫不存在的類型轉換爲數據庫存在的類型,你需要提供他們互轉的方法,定義轉化類。

添加索引並指定唯一性

現在呢,我想將姓名添加爲索引,並且是唯一的,需要這麼做

@Entity(indices = arrayOf(Index(value = arrayOf("name"),unique = true)))
@TypeConverters(StringConverter::class)
data class User(
   	...
)

由於表結構變化需要升級數據庫(注:entity一旦改變則需要升級數據庫

@Database(entities = arrayOf(User::class),version = 3)
abstract class AppDataBase :RoomDatabase(){

    abstract fun getUserDao():UserDao


    companion object{
        private var instance:AppDataBase?=null

        fun getInstance(context: Context):AppDataBase{
            if (instance==null){
                synchronized(AppDataBase::class){
                    if (instance==null){
                        instance=Room.databaseBuilder(context,AppDataBase::class.java,"room")
                            .addMigrations(object :Migration(1,2){
                                override fun migrate(database: SupportSQLiteDatabase) {
                                    database.run {
                                        execSQL("alter table User add COLUMN likes TEXT")
                                    }
                                }

                            },object :Migration(2,3){
                                override fun migrate(database: SupportSQLiteDatabase) {
                                    database.run {
                                        execSQL("create UNIQUE index index_User_name on User(name)")
                                    }
                                }

                            })
                            .build()
                    }
                }
            }
            return instance!!
        }

    }
}

這個時候再添加同姓名的數據則會報UNIQUE constraint failed: User.name 錯誤。

更新用戶信息

現在呢,我想將名字爲張三的用戶的年齡修改成23,怎麼做呢?

@Dao
@TypeConverters(StringConverter::class)
interface UserDao {
   ...
   /**
   *更新用戶年齡
   **/
    @Query("update user set age = :age where name = :name")
    fun updateAgeByName(name:String,age:Int):Int
    

對,你沒有看錯,它使用的是@Query,返回值是Int。

結語

回顧一下,本文主要講述了Room建表,增、刪、改、查操作,字段類型轉換,添加索引,數據庫升級操作,都是一些比較基礎的東西,至於多表之間的操作,如通過添加外鍵實現一對多,多對多,@Relation的使用等之後再做總結。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章