Android Room使用

簡介

Room庫在SQLite上提供了一個抽象層,允許在充分利用SQLite的功能的同時進行更健壯的數(shù)據(jù)庫訪問??梢栽谶\行的app設備上創(chuàng)建一個應用數(shù)據(jù)緩存,這個緩存作為app的唯一數(shù)據(jù)來源,不管用戶是否有連接網(wǎng)絡,都允許用戶在app中查看相關(guān)信息。
Room有三個主要的組成部分:Database,Entity,DAO。

  • Database:數(shù)據(jù)庫容器,并作為到應用程序的持久關(guān)系數(shù)據(jù)的底層連接的主要訪問點。

    使用@Database注釋的類應該滿足以下條件:

    • 擴展RoomDatabase的抽象類
    • 在注釋中包含與數(shù)據(jù)庫關(guān)聯(lián)的實體列表
    • 包含一個具有0個參數(shù)的抽象方法,并返回用@Dao注釋的類

在運行時,您可以通過調(diào)用Room.databaseBuilder()或Room.inMemoryDatabaseBuilder()來獲取數(shù)據(jù)庫實例。

  • Entity:表示數(shù)據(jù)庫中的表。
  • DAO:包含用于訪問數(shù)據(jù)庫的方法。
Room不同組成的相關(guān)關(guān)系圖

引用

在project的build.gradle添加google的maven倉庫

allprojects {
    repositories {
        google()
        jcenter()
    }
}

在module的build.gradle添加Room的引用,Room還提供了Rxjava2和Guava的數(shù)據(jù)處理

dependencies {
    def room_version = "2.1.0-alpha07"

    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of annotationProcessor

    // optional - Kotlin Extensions and Coroutines support for Room
    implementation "androidx.room:room-ktx:$room_version"

    // optional - RxJava support for Room
    implementation "androidx.room:room-rxjava2:$room_version"

    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation "androidx.room:room-guava:$room_version"

    // Test helpers
    testImplementation "androidx.room:room-testing:$room_version"
}

Enity

下面定義一個User的實體

@Entity
data class User(
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = "first_name") val firstName: String?,
    @ColumnInfo(name = "second_name") val secondName: String?,
    @Ignore val desc: String?
)
  • 表名:Room使用實體類的名字作為數(shù)據(jù)庫表的名字,如果想更改表名,可以使用@Entity(tableName = "users")更改。
  • 主鍵:每個實體都需要定義最少一個主鍵,可以直接在字段使用@PrimaryKey標注主鍵,想Room分配自動ID可使用autoGenerate屬性,也可以使用復合主鍵@Entity(primaryKeys = ["second_name","first_name" ])
  • 字段名:字段的名字默認的也是類中屬性的名字如果想設置其他名字,可使用@ColumnInfo(name = "first_name"),Room為每個字段在表中創(chuàng)建對應的字段;如果其中一些屬性不想被創(chuàng)建在表中怎么辦,那就是使用 @Ignore 注解此屬性
  • 索引和唯一約束:使用 @Entity 的 indices 來創(chuàng)建索引,并列出索引或者組合索引包含的列,可以使用unique屬性設置唯一約束Index(value = ["name"], unique = true)
@Entity(indices = [Index("name"), Index(value = ["first_name", "second_name"])])
data class User(
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = "first_name") val firstName: String?,
    @ColumnInfo(name = "second_name") val secondName: String?,
    @Ignore val desc: String?
)
  • 外鍵:可以使用@ForeignKey 定義對象間的級聯(lián)操作
@Entity(foreignKeys = [ForeignKey(entity = User::class, parentColumns = ["uid"], childColumns = ["user_id"])])
data class Order(
    @PrimaryKey val orderNo: String,
    @ColumnInfo val address: String,
    @ColumnInfo(name = "user_id") val userId: Int
)
  • 嵌套對象:可以使用@Embedded 嵌套其他實體對象,可以通過設置屬性 prefix 加前綴的方式保證字段名不重復。
@Embedded(prefix = "order") val order: Order?

DAO

定義一個User的數(shù)據(jù)訪問類

@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    fun getAll(): List<User>

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    fun loadAllByIds(userIds: IntArray): List<User>

    @Query("SELECT * FROM user where first_name LIKE :first AND second_name LIKE :last LIMIT 1 ")
    fun findByName(first: String, last: String): User

    @Insert
    fun insertAll(vararg users: User)

    @Delete
    fun delete(user: User)
    
    @Update
    fun updateUsers(vararg users: User)
}
  • 插入:使用@Insert注解,Room將把所有的參數(shù)在一次事物中插入到數(shù)據(jù)庫中,Insert的參數(shù)onConflict用來指定當發(fā)生沖突是的策略。比如將@Index的unique屬性設置為true,當產(chǎn)生沖突時,默認情況下為OnConflictStrategy.ABORT會導致崩潰,這里設置為OnConflictStrategy.REPLACE,當發(fā)生沖突時替換老數(shù)據(jù)
  • 更新:使用@Update注解方法,可以使用參數(shù)實體的值更新主鍵值和參數(shù)實體的主鍵相同的行
  • 刪除:@Delete注解方法,可以刪除主鍵值和參數(shù)實體的主鍵相同的行
  • 查詢:@Query支持查詢語句,刪除語句和更新語句,不支持插入語句。傳入?yún)?shù)使用“:參數(shù)名”來進行綁定。
    • 可觀察查****詢

在執(zhí)行查詢時,想讓UI在數(shù)據(jù)更改時自動更新??梢栽诓樵兎椒ㄊ褂?LiveData 類行的返回值。當數(shù)據(jù)更新時 Room 會自動生成所需的代碼已更新LiveData。

@Query("SELECT * FROM user WHERE uid IN (:userIds)")
fun getList(userIds: IntArray): LiveData<List<User>>
  • 響應查詢

可以從定義的查詢中返回 RxJava2 的 Publisher 和 Flowable 對象

@Query("SELECT * FROM user where first_name LIKE :first AND second_name LIKE :last LIMIT 1 ")
fun getByName(first: String, last: String): Flowable<User>

Database

@Database(entities = arrayOf(User::class), version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

創(chuàng)建完完成后使用以下代碼獲取數(shù)據(jù)庫實例,并且使用單例來訪問

var db = Room.databaseBuilder(
    getApplicationContext(),
    AppDatabase::class.java, "database-name"
).build()

遷移數(shù)據(jù)庫

在APP升級時可能需要更改數(shù)據(jù)庫來策應新的功能。如果不希望數(shù)據(jù)庫中的數(shù)據(jù)丟失,
Room 允許我們編寫 Migration ,以此來遷移數(shù)據(jù);如果使用fallbackToDestructiveMigration(),數(shù)據(jù)庫的內(nèi)容都被清空。
每個遷移類制定一個開始版本和結(jié)束版本。在運行時,Room會運行每個Migration類的migrate()方法,并使用正確的順序?qū)?shù)據(jù)庫遷移到更高版本。
首先,需要更新Database的版本號

@Database(entities = arrayOf(User::class), version = 2)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

其次添加一個version:1->2的migration

val MIGRATION_1_2: Migration = object : Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("ALTER TABLE User " + " ADD COLUMN mobile TEXT")
    }
}

最后把migration 添加到 databaseBuilder,addMigrations提供可選參數(shù),支持多版本遷移,傳入多個migration。

var db = Room.databaseBuilder(
    getApplicationContext(),
    AppDatabase::class.java, "database-name"
).allowMainThreadQueries()
    .addMigrations(MIGRATION_1_2).build()

Room的基本用法介紹已經(jīng)END。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 介紹 Room是Google提供的一個ORM庫。Room提供了三個主要的組件: @Database:@Databa...
    Carve_Time閱讀 61,815評論 11 106
  • 一、概述 Room提供了一個訪問SQLite的抽象層,以便在利用SQLite的全部功能的同時進行流暢的數(shù)據(jù)庫訪問。...
    小村醫(yī)閱讀 23,401評論 4 17
  • 原文地址:Android Room with a view Android推薦的架構(gòu)組件 Entity: 當使用架...
    nxiangbo閱讀 18,509評論 1 16
  • Room持久性庫在SQLite的基礎(chǔ)上提供了一個抽象層,允許流利的數(shù)據(jù)庫訪問,同時利用的SQLite的全部力量。該...
    yyg閱讀 5,551評論 0 5
  • Room是一個對象關(guān)系映射(ORM)庫。Room抽象了SQLite的使用,可以在充分利用SQLite的同時訪...
    tuacy閱讀 54,492評論 16 109

友情鏈接更多精彩內(nèi)容