亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

快速了解Android?Room使用細(xì)則進(jìn)階

 更新時(shí)間:2023年03月02日 14:41:51   作者:AlbertZein  
這篇文章主要為大家介紹了快速了解Android?Room使用細(xì)則進(jìn)階,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

1、前言

上一篇5分鐘帶你了解Android Room數(shù)據(jù)好起來了,有人催更,遂決定再寫一篇Room的使用,這篇我們著重講講注解。如果寫的不好,或者有錯(cuò)誤之處,懇請(qǐng)?jiān)谠u(píng)論、私信、郵箱指出,萬分感謝??

2、@ForeignKey和@PrimaryKey

考驗(yàn)?zāi)銛?shù)據(jù)庫知識(shí)的時(shí)候來了!因?yàn)槟銜?huì)頻繁看到@PrimaryKey所以先講它

@ForeignKey 注解用于定義外鍵關(guān)系,它指定了一個(gè)實(shí)體類中的一個(gè)字段是另一個(gè)實(shí)體類的主鍵。這種關(guān)系被稱為“外鍵關(guān)系”,并且可以用于在多個(gè)表之間建立關(guān)聯(lián)。

例如,如果有兩個(gè)實(shí)體類 UserAddress,并且想要將它們關(guān)聯(lián)起來,則可以使用 @ForeignKey 注解來指定 Address 中的 user_id 字段是 User 的主鍵:

@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    val name: String
)
@Entity(tableName = "addresses",
        foreignKeys = [
            ForeignKey(entity = User::class,
                       parentColumns = ["id"],
                       childColumns = ["user_id"],
                       onDelete = ForeignKey.CASCADE)
        ])
data class Address(
    @PrimaryKey val id: Int,
    val street: String,
    val city: String,
    val state: String,
    val zip: String,
    @ColumnInfo(name = "user_id") val userId: Int
)

在這個(gè)例子中,我們使用 @ForeignKey 注解將 Address 中的 user_id 字段指定為 User 的主鍵。這將創(chuàng)建一個(gè)外鍵關(guān)系,確保在插入或更新 Address 表中的數(shù)據(jù)時(shí),user_id 字段的值必須是 User 表中存在的主鍵值之一。

@PrimaryKey 注解用于指定實(shí)體類中的一個(gè)字段是主鍵。主鍵是用于唯一標(biāo)識(shí)每個(gè)實(shí)體類對(duì)象的字段。在 Room 中,每個(gè)實(shí)體類必須至少有一個(gè)字段被指定為主鍵。

例如,如果有一個(gè)實(shí)體類 User,并且想要將 id 字段指定為主鍵,則可以使用 @PrimaryKey 注解:

@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    val name: String
)

在這個(gè)例子中,我們使用 @PrimaryKey 注解將 id 字段指定為 User 實(shí)體類的主鍵。這將確保在插入或更新 User 表中的數(shù)據(jù)時(shí),每個(gè) id 字段的值都是唯一的。

3、@TypeConverters

在使用Room時(shí),你可能會(huì)遇到需要在Entity類中使用非基本類型的情況,例如Date、Calendar、List等類型。在這種情況下,你可以使用TypeConverters將這些類型轉(zhuǎn)換為Room可以存儲(chǔ)的類型。在Room中,可以使用@TypeConverter注解來定義一個(gè)類型轉(zhuǎn)換器,例如:

class Converters {
    @TypeConverter
    fun fromDate(date: Date): Long {
        return date.time
    }
    @TypeConverter
    fun toDate(timestamp: Long): Date {
        return Date(timestamp)
    }
    @TypeConverter
    fun fromList(list: List<String>?): String? {
        return list?.joinToString(",")
    }
    @TypeConverter
    fun toList(string: String?): List<String>? {
        return string?.split(",")
    }
}
@Entity(tableName = "user")
@TypeConverters(Converters::class)
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    val birthday: Date
  	@TypeConverters(HobbiesConverter::class) val hobbies: List<String>
)
@Database(entities = [User::class], version = 1)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
    // ...
}
@Dao
@TypeConverters(Converters::class)
interface UserDao {
    @Query("SELECT * FROM user")
    fun getAll(): List<User>
}

示例代碼在非常多的地方使用了@TypeConverters ,不同的位置造成的影響也是不同的,實(shí)際上可以應(yīng)用到以下四個(gè)地方:

  • 實(shí)體類:在 @Entity 注解中使用,可以在處理該實(shí)體類時(shí)使用它們。
  • DAO 接口:在 DAO 接口中使用,可以在執(zhí)行該 DAO 中的查詢時(shí)使用它們。
  • 數(shù)據(jù)庫類:在 RoomDatabase 類中使用, 可以在整個(gè)數(shù)據(jù)庫中使用它們。
  • 實(shí)體類中的屬性:在實(shí)體類中的屬性,可以在處理該屬性時(shí)使用指定的類型轉(zhuǎn)換器

4、@Relation

@Relation 用于在實(shí)體類之間建立關(guān)系。它可以用于定義兩個(gè)或更多實(shí)體之間的關(guān)系,這些實(shí)體可以在數(shù)據(jù)庫中分別存儲(chǔ)在不同的表中。

@Relation 注解應(yīng)該與 @Query 注解一起使用,以便 Room 可以在查詢結(jié)果中返回相關(guān)實(shí)體之間的關(guān)系。@Relation 注解的一個(gè)常見用例是定義父子關(guān)系,其中一個(gè)實(shí)體包含對(duì)另一個(gè)實(shí)體的引用。

@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    val email: String
)
@Entity(tableName = "books")
data class Book(
    @PrimaryKey val id: Int,
    val title: String,
    val author: String,
    val userId: Int
)
data class UserWithBooks(
    @Embedded val user: User,
    @Relation(
        parentColumn = "id",
        entityColumn = "userId"
    )
    val books: List<Book>
)

在這個(gè)示例中,我們有兩個(gè)實(shí)體類 UserBook,它們之間有一個(gè)父子關(guān)系,其中一個(gè)用戶可以擁有多本書。然后,我們定義了一個(gè) UserWithBooks 數(shù)據(jù)類,它包含一個(gè)嵌套的 User 實(shí)體和一個(gè) @Relation 注解,用于指定如何檢索與該用戶關(guān)聯(lián)的所有書籍。@Relation 注解包括 parentColumnentityColumn 參數(shù),分別指定父實(shí)體的主鍵列和子實(shí)體的外鍵列。

當(dāng)我們使用 @Relation 注解時(shí),我們需要在查詢中使用 SELECT 語句,以便 Room 可以檢索相關(guān)的實(shí)體。例如,在 Dao 接口中,我們可以使用以下查詢:

//Transaction下一點(diǎn)就會(huì)說
@Transaction
@Query("SELECT * FROM users WHERE id = :id")
fun getUserWithBooks(id: Int): UserWithBooks

此外,我們使用 SELECT * 語句來檢索所有用戶屬性和相關(guān)的書籍列表,因?yàn)?UserWithBooks 數(shù)據(jù)類包含一個(gè)嵌套的 User 實(shí)體和一個(gè) List<Book> 列表。

5、@Transaction

第4點(diǎn)說到@Relation時(shí)使用到了@Transaction。在這個(gè)查詢中,我們使用 @Transaction 注解來確保整個(gè)查詢作為一個(gè)事務(wù)執(zhí)行,以便 Room 可以在單個(gè)操作中檢索 User 實(shí)體和與之相關(guān)的所有 Book 實(shí)體。

@Transaction用于將一組數(shù)據(jù)庫操作包裝在一個(gè)事務(wù)中。它可以確保在執(zhí)行數(shù)據(jù)庫操作時(shí)保持?jǐn)?shù)據(jù)庫的一致性,并在必要時(shí)回滾事務(wù)以確保數(shù)據(jù)的完整性。

在 Room 中,單個(gè)數(shù)據(jù)庫操作(例如插入、更新或刪除)是自動(dòng)運(yùn)行在事務(wù)中的。但是,當(dāng)需要執(zhí)行多個(gè)數(shù)據(jù)庫操作時(shí),可能需要手動(dòng)創(chuàng)建一個(gè)事務(wù)來確保這些操作原子性地執(zhí)行。如果需要執(zhí)行多個(gè)數(shù)據(jù)庫操作,請(qǐng)始終考慮使用 @Transaction 注解。這可以避免數(shù)據(jù)不一致和其他與數(shù)據(jù)庫操作相關(guān)的問題。

6、@Embedded

上一篇,有同志說@Embedded很好用,的確如此哈

@Embedded用于指定一個(gè)實(shí)體類中的一個(gè)或多個(gè)字段應(yīng)該作為其所屬的另一個(gè)實(shí)體的嵌入式對(duì)象。這使得 Room 可以將多個(gè)相關(guān)實(shí)體的數(shù)據(jù)組合成一個(gè)單獨(dú)的對(duì)象,從而簡(jiǎn)化了數(shù)據(jù)庫操作。

當(dāng)在一個(gè)實(shí)體類中使用 @Embedded 注解時(shí),可以指定該實(shí)體類中的一個(gè)或多個(gè)字段應(yīng)該嵌入到另一個(gè)實(shí)體類中。例如,假設(shè)有一個(gè) Address 實(shí)體類和一個(gè) User 實(shí)體類,其中 User 實(shí)體類包含一個(gè) Address 對(duì)象??梢允褂?@Embedded 注解將 Address 對(duì)象嵌入到 User 實(shí)體類中:

@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    @Embedded val address: Address
)
data class Address(
    val street: String,
    val city: String,
    val state: String,
    val zip: String
)

在這個(gè)例子中,User 實(shí)體類包含一個(gè) Address 對(duì)象,它使用 @Embedded 注解指定了該對(duì)象應(yīng)該嵌入到 User 實(shí)體類中。在查詢數(shù)據(jù)庫時(shí),Room 將自動(dòng)組合 User 實(shí)體類和 Address 實(shí)體類中的字段,以便可以輕松地訪問和操作它們。

還可以使用 prefix 參數(shù)來指定 Room 應(yīng)該在組合兩個(gè)實(shí)體類中的字段時(shí)使用的前綴。例如:

@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    @Embedded(prefix = "home_") val homeAddress: Address,
    @Embedded(prefix = "work_") val workAddress: Address
)

在這個(gè)例子中,User 實(shí)體類包含兩個(gè) Address 對(duì)象,一個(gè)是 homeAddress,另一個(gè)是 workAddress。我們使用 @Embedded(prefix = "home_")@Embedded(prefix = "work_") 注解為每個(gè)地址對(duì)象指定了不同的前綴。這使得 Room 可以區(qū)分兩個(gè)地址對(duì)象中的相同字段,并將它們組合成一個(gè)單獨(dú)的對(duì)象。

當(dāng)然你也可以這么干

@Entity(tableName 
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    @Embedded @ColumnInfo(name = "home_address") val homeAddress: Address
)

7、@ColumnInfo

可以看到,我們剛剛用到了@ColumnInfo這個(gè)注解,用于自定義實(shí)體類中的列名、默認(rèn)值和其他屬性。當(dāng)需要將一個(gè)實(shí)體類映射到數(shù)據(jù)庫表時(shí),可以使用 @ColumnInfo 注解來指定實(shí)體類中的每個(gè)字段在數(shù)據(jù)庫表中的名稱和其他屬性。

(1)指定實(shí)體類中的字段名稱

@ColumnInfo 注解最常用的用途是指定實(shí)體類中的字段名稱。例如:

@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    @ColumnInfo(name = "full_name") val name: String,
    val age: Int
)

在這個(gè)例子中,我們使用 @ColumnInfo(name = "full_name")name 字段的名稱指定為 full_name。這意味著在數(shù)據(jù)庫表中,這個(gè)字段將被命名為 full_name,而不是 name。

(2)指定實(shí)體類中的字段默認(rèn)值

@ColumnInfo 注解還可以用于指定實(shí)體類中的字段默認(rèn)值。例如:

@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    @ColumnInfo(name = "full_name") val name: String,
    @ColumnInfo(name = "is_active") val isActive: Boolean = true
)

在這個(gè)例子中,我們使用 @ColumnInfo(name = "is_active")isActive 字段的名稱指定為 is_active,并將其默認(rèn)值設(shè)置為 true。這意味著在數(shù)據(jù)庫表中,這個(gè)字段將被命名為 is_active,并且默認(rèn)值將為 true。

(3)指定實(shí)體類中的字段約束

@ColumnInfo 注解還可以用于指定實(shí)體類中的字段約束。例如:

@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    @ColumnInfo(name = "full_name") val name: String,
    @ColumnInfo(name = "is_active") val isActive: Boolean = true,
    @ColumnInfo(name = "created_at", defaultValue = "CURRENT_TIMESTAMP") val createdAt: String
)

在這個(gè)例子中,我們使用 @ColumnInfo(name = "created_at", defaultValue = "CURRENT_TIMESTAMP")createdAt 字段的名稱指定為 created_at,并將其默認(rèn)值設(shè)置為 CURRENT_TIMESTAMP。這意味著在數(shù)據(jù)庫表中,這個(gè)字段將被命名為 created_at,并且默認(rèn)值將為 CURRENT_TIMESTAMP

8、@Ignore

很直觀的注解哈。指定實(shí)體類中應(yīng)該忽略的字段。當(dāng)需要在實(shí)體類中添加一個(gè)字段,但不想將其映射到數(shù)據(jù)庫表中時(shí),可以使用 @Ignore 注解來指定該字段應(yīng)該被忽略。

忽略一個(gè)實(shí)體類中的字段

@Ignore 注解最常用的用法是忽略一個(gè)實(shí)體類中的字段,從而防止該字段被映射到數(shù)據(jù)庫表中。例如:

@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    @Ignore val password: String
)

在這個(gè)例子中,我們使用 @Ignorepassword 字段指定為應(yīng)該被忽略的字段。這意味著在數(shù)據(jù)庫表中,這個(gè)字段將不會(huì)出現(xiàn),也不會(huì)被映射到 User 實(shí)體類中。

(1)忽略一個(gè)實(shí)體類中的 getter 和 setter 方法

除了忽略一個(gè)實(shí)體類中的字段外,@Ignore 注解還可以用于忽略一個(gè)實(shí)體類中的 getter 和 setter 方法。這可以幫助控制 Room 如何處理實(shí)體類中的方法。

例如,如果希望 Room 不生成一個(gè)實(shí)體類中的 setter 方法,則可以將 @Ignore 注解添加到該方法上:

@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    val password: String
) {
    @Ignore
    fun setPassword(password: String) {
        // ...
    }
}

在這個(gè)例子中,我們使用 @IgnoresetPassword 方法指定為應(yīng)該被忽略的方法。這意味著 Room 不會(huì)生成一個(gè) setter 方法來設(shè)置 password 字段的值。

(2)忽略一個(gè)實(shí)體類中的整個(gè)構(gòu)造函數(shù)

最后,@Ignore 注解還可以用于忽略一個(gè)實(shí)體類中的整個(gè)構(gòu)造函數(shù)。這可以幫助控制 Room 如何處理實(shí)體類中的構(gòu)造函數(shù)。

例如,如果希望 Room 不使用默認(rèn)的構(gòu)造函數(shù)來創(chuàng)建實(shí)體類的實(shí)例,則可以使用 @Ignore 注解標(biāo)記該構(gòu)造函數(shù):

@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    val password: String
) {
    @Ignore
    constructor(id: Int, name: String) : this(id, name, "")
}

在這個(gè)例子中,我們使用 @Ignore 將第二個(gè)構(gòu)造函數(shù)指定為應(yīng)該被忽略的構(gòu)造函數(shù)。這意味著 Room 不會(huì)使用這個(gè)構(gòu)造函數(shù)來創(chuàng)建 User 實(shí)體類的實(shí)例。

9、@Index

考驗(yàn)?zāi)銛?shù)據(jù)庫知識(shí)的時(shí)候來了!索引(個(gè)索引、多個(gè)索引、復(fù)合索引)可以提高數(shù)據(jù)庫表查詢的性能,因?yàn)樗鼈兪箶?shù)據(jù)庫系統(tǒng)能夠更快地查找和排序表中的數(shù)據(jù)。

(1)在一個(gè)實(shí)體類中創(chuàng)建單個(gè)索引

@Index 注解最常用的用法是在一個(gè)實(shí)體類中創(chuàng)建單個(gè)索引。例如:

@Entity(tableName = "users", indices = [Index(value = ["name"])])
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    val age: Int
)

在這個(gè)例子中,我們使用 @Index 注解在 name 字段上創(chuàng)建了一個(gè)單個(gè)索引。這將使數(shù)據(jù)庫系統(tǒng)能夠更快地查找和排序 User 表中的數(shù)據(jù)。

(2)在一個(gè)實(shí)體類中創(chuàng)建多個(gè)索引

除了在一個(gè)實(shí)體類中創(chuàng)建單個(gè)索引外,@Index 注解還可以用于在一個(gè)實(shí)體類中創(chuàng)建多個(gè)索引。例如:

@Entity(tableName = "users", indices = [
    Index(value = ["name"]),
    Index(value = ["age"])
])
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    val age: Int
)

在這個(gè)例子中,我們使用 @Index 注解在 nameage 字段上創(chuàng)建了兩個(gè)索引。這將使數(shù)據(jù)庫系統(tǒng)能夠更快地查找和排序 User 表中的數(shù)據(jù)。

(3)在一個(gè)實(shí)體類中創(chuàng)建復(fù)合索引

@Index 注解還可以用于在一個(gè)實(shí)體類中創(chuàng)建復(fù)合索引。復(fù)合索引是指將多個(gè)字段組合在一起以創(chuàng)建一個(gè)索引,這將使數(shù)據(jù)庫系統(tǒng)能夠更快地查找和排序這些字段的組合。

例如,如果希望在 User 表中按照 nameage 字段的組合進(jìn)行排序,則可以使用 @Index 注解來創(chuàng)建一個(gè)復(fù)合索引:

@Entity(tableName = "users", indices = [
    Index(value = ["name", "age"])
])
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    val age: Int
)

在這個(gè)例子中,我們使用 @Index 注解在 nameage 字段上創(chuàng)建了一個(gè)復(fù)合索引。這將使數(shù)據(jù)庫系統(tǒng)能夠更快地查找和排序 User 表中按照 nameage 字段的組合進(jìn)行排序的數(shù)據(jù)。

10、@Entity

當(dāng)在 Room 中定義一個(gè)實(shí)體類時(shí),必須使用 @Entity 注解來指定該類應(yīng)該被映射到數(shù)據(jù)庫中的哪個(gè)表。

(1)在一個(gè)實(shí)體類中指定表名

@Entity 注解最常用的用法是在一個(gè)實(shí)體類中指定表名。例如:

@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    val age: Int
)

在這個(gè)例子中,我們使用 @Entity 注解將 User 實(shí)體類映射到名為 users 的數(shù)據(jù)庫表中。這將使 Room 能夠?qū)?User 類中的字段映射到數(shù)據(jù)庫表中的相應(yīng)列中。

(2)在一個(gè)實(shí)體類中指定索引

除了在一個(gè)實(shí)體類中指定表名外,@Entity 注解還可以用于在一個(gè)實(shí)體類中指定索引。索引可以提高數(shù)據(jù)庫表查詢的性能,因?yàn)樗鼈兪箶?shù)據(jù)庫系統(tǒng)能夠更快地查找和排序表中的數(shù)據(jù)。

例如,如果希望在 User 表中按照 name 字段進(jìn)行排序,則可以使用 @Entity 注解來創(chuàng)建一個(gè)索引:

@Entity(tableName = "users", indices = [Index(value = ["name"])])
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    val age: Int
)

在這個(gè)例子中,我們使用 @Entity 注解在 name 字段上創(chuàng)建了一個(gè)索引。這將使數(shù)據(jù)庫系統(tǒng)能夠更快地查找和排序 User 表中的數(shù)據(jù)。

(3)在一個(gè)實(shí)體類中指定繼承關(guān)系

最后,@Entity 注解還可以用于在一個(gè)實(shí)體類中指定繼承關(guān)系。如果的實(shí)體類繼承自另一個(gè)實(shí)體類,則可以使用 @Entity 注解來指定它們之間的關(guān)系。

例如,如果有一個(gè) Person 實(shí)體類和一個(gè) Employee 實(shí)體類,Employee 實(shí)體類繼承自 Person 實(shí)體類,則可以使用 @Entity 注解來指定它們之間的關(guān)系:

@Entity(tableName = "user")
open class User(
    @PrimaryKey val id: Int,
    val name: String
)
@Entity(tableName = "employees")
data class Employee(
    @PrimaryKey val id: Int,
    val salary: Int,
    @ColumnInfo(name = "user_id") val userId: Int
) : User(userId, "")

在這個(gè)例子中,我們使用 @Entity 注解將 Person 實(shí)體類映射到名為 people 的數(shù)據(jù)庫表中,并將 Employee 實(shí)體類映射到名為 employees 的數(shù)據(jù)庫表中。此外,我們還使用 @Entity 注解指定了 Employee 實(shí)體類繼承自 Person 實(shí)體類,并使用 @ColumnInfo 注解將 person_id 字段指定為 Employee 表中的外鍵。這將確保在插入或更新 Employee 表中的數(shù)據(jù)時(shí),person_id 字段的值必須是 Person 表中存在的主鍵值之一。

11、@Dao

@Dao 是用于訪問數(shù)據(jù)庫中數(shù)據(jù)的一種抽象層。在 Room 中,每個(gè) DAO 都定義了一組用于與數(shù)據(jù)庫進(jìn)行交互的方法。意思是就這么用,沒啦。

@Dao
interface UserDao {}

12、@Database

@Database 注解是 Room 中的一個(gè)注解,用于定義數(shù)據(jù)庫類。當(dāng)在 Room 中定義一個(gè)數(shù)據(jù)庫時(shí),必須使用 @Database 注解來指定該數(shù)據(jù)庫包含哪些實(shí)體類和版本號(hào)等信息。

(1)在一個(gè)類中定義數(shù)據(jù)庫實(shí)例

@Database 注解最常用的用法是在一個(gè)類中定義數(shù)據(jù)庫實(shí)例。例如:

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

在這個(gè)例子中,我們使用 @Database 注解定義了一個(gè)數(shù)據(jù)庫類 AppDatabase,并在其中指定了包含 User 實(shí)體類的數(shù)據(jù)庫版本號(hào)。此外,我們還定義了一個(gè)抽象方法 userDao(),用于返回一個(gè) UserDao 數(shù)據(jù)訪問對(duì)象 (DAO)。

(2)指定多個(gè)實(shí)體類

@Database 注解還可以用于指定多個(gè)實(shí)體類。例如:

@Database(entities = [User::class, Address::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
    abstract fun addressDao(): AddressDao
}

在這個(gè)例子中,我們使用 @Database 注解指定了包含 UserAddress 實(shí)體類的數(shù)據(jù)庫版本號(hào)。然后,我們定義了兩個(gè)抽象方法 userDao()addressDao(),分別用于返回 UserDaoAddressDao 數(shù)據(jù)訪問對(duì)象 (DAO)。

(3)指定數(shù)據(jù)庫升級(jí)策略

最后,@Database 注解還可以用于指定數(shù)據(jù)庫升級(jí)策略。當(dāng)升級(jí)數(shù)據(jù)庫時(shí),可能需要指定一些操作來處理數(shù)據(jù)模式的變化。Room 提供了兩種升級(jí)策略:MigrateFallbackToDestructiveMigration

例如,如果希望在升級(jí)數(shù)據(jù)庫時(shí)保留現(xiàn)有數(shù)據(jù),可以使用 Migrate 升級(jí)策略:

val migration1to2 = object : Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        // TODO: write migration code here
    }
}
@Database(entities = [User::class], version = 2, migrations = [migration1to2])
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

在這個(gè)例子中,我們使用 Migrate 升級(jí)策略將數(shù)據(jù)庫版本從 1 升級(jí)到 2。我們定義了一個(gè)名為 migration1to2 的遷移對(duì)象,用于在升級(jí)數(shù)據(jù)庫時(shí)執(zhí)行自定義的 SQL 語句。然后,我們使用 @Database 注解指定了包含 User 實(shí)體類的數(shù)據(jù)庫版本號(hào)和升級(jí)策略。

如果不需要保留現(xiàn)有數(shù)據(jù),可以使用 FallbackToDestructiveMigration 升級(jí)策略:

@Database(entities = [User::class], version = 2, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
    companion object {
        @Volatile
        private var instance: AppDatabase? = null
        fun getInstance(context: Context): AppDatabase {
            return instance ?: synchronized(this) {
                instance ?: buildDatabase(context).also { instance = it }
            }
        }
        private fun buildDatabase(context: Context): AppDatabase {
            return Room.databaseBuilder(context, AppDatabase::class.java, "app-database")
                .fallbackToDestructiveMigration().build()
        }
    }
}

在這個(gè)例子中,我們使用 FallbackToDestructiveMigration 升級(jí)策略將數(shù)據(jù)庫版本從 1 升級(jí)到 2。我們使用 @Database 注解指定了包含 User 實(shí)體類的數(shù)據(jù)庫版本號(hào)和升級(jí)策略,并將 exportSchema 參數(shù)設(shè)置為 false,以避免生成不必要的 JSON 文件。

13、@Query

用于定義SQL查詢語句,可以在之前的例子中找到,許多的@Query的身影 (考驗(yàn)?zāi)銛?shù)據(jù)庫基礎(chǔ)的時(shí)候到了?。?/p>

(1)基本查詢操作

@Query 注解最常用的用法是執(zhí)行基本的查詢操作。例如:

@Dao
interface UserDao {
    @Query("SELECT * FROM users")
    fun getAllUsers(): List<User>
}

在這個(gè)例子中,我們使用 @Query 注解定義了一個(gè)基本的 SQL 查詢語句,該語句將返回 users 表中的所有數(shù)據(jù)。我們將此查詢定義為 getAllUsers() 方法的一部分,以便在需要時(shí)調(diào)用該方法。

(2)帶參數(shù)的查詢操作

@Query 注解還可以用于執(zhí)行帶參數(shù)的查詢操作。例如:

@Dao
interface UserDao {
    @Query("SELECT * FROM users WHERE id = :id")
    fun getUserById(id: Int): User
}

在這個(gè)例子中,我們使用 @Query 注解定義了一個(gè)帶有參數(shù)的 SQL 查詢語句,該語句將返回 users 表中 id 字段等于給定值的數(shù)據(jù)。我們將此查詢定義為 getUserById() 方法的一部分,并將 id 參數(shù)傳遞給查詢語句。

(3)使用關(guān)聯(lián)查詢

最后,@Query 注解還可以用于執(zhí)行關(guān)聯(lián)查詢。關(guān)聯(lián)查詢是一種可以跨多個(gè)表查詢數(shù)據(jù)的查詢類型。

@Dao
interface UserDao {
    @Query("SELECT * FROM users INNER JOIN addresses ON users.address_id = addresses.id")
    fun getUsersWithAddresses(): List<UserWithAddress>
}

在這個(gè)例子中,我們使用 @Query 注解定義了一個(gè)關(guān)聯(lián)查詢語句,該語句將返回 users 表中的數(shù)據(jù)以及與之關(guān)聯(lián)的 addresses 表中的數(shù)據(jù)。我們將此查詢定義為 getUsersWithAddresses() 方法的一部分,并使用 INNER JOIN 子句指定 users 表和 addresses 表之間的關(guān)系。

14、@Insert、@Update、@Delete

顧名思義哈,也就不用舉例了,嘻嘻嘻

@Dao
interface UserDao {
    @Insert\@Update\@Delete
    fun xxxUser(user: User)
}

15、多數(shù)據(jù)源

使用Kotlin Flow可以很方便地處理多個(gè)數(shù)據(jù)源的情況。在使用Room時(shí),我們可以在Repository層中實(shí)現(xiàn)本地和遠(yuǎn)程數(shù)據(jù)源的邏輯,并使用Kotlin Flow來組合和轉(zhuǎn)換數(shù)據(jù)。

以下是一個(gè)示例,演示了如何使用Room和Kotlin Flow處理多個(gè)數(shù)據(jù)源的情況:

class UserRepository(
    private val userDao: UserDao,
    private val api: ApiService
) {
    fun getUsers(): Flow<List<User>> {
        val localUsers = userDao.getAll().asFlow()
        val remoteUsers = api.getUsers().asFlow()
        return localUsers.combine(remoteUsers) { local, remote ->
            // 合并本地和遠(yuǎn)程數(shù)據(jù)
            (local + remote).distinctBy { it.id }
        }
    }
    suspend fun updateUser(user: User) {
        api.updateUser(user.id, user)
        userDao.update(user)
    }
}

在以上示例中,我們?cè)赨serRepository中使用了本地和遠(yuǎn)程數(shù)據(jù)源,并使用Kotlin Flow.combine操作符將本地和遠(yuǎn)程數(shù)據(jù)源合并在一起,并在最后返回一個(gè)Flow對(duì)象。我們還使用了suspend修飾符將updateUser方法標(biāo)記為掛起函數(shù),以便可以在協(xié)程中執(zhí)行異步操作。

很方便吧

16、@Fts3和@Fts4

這個(gè)一般用不到來著,不過如果你要做小說軟件的話,可能有用。用于創(chuàng)建全文本搜索虛擬表。全文本搜索是一種在大型文本數(shù)據(jù)集中搜索特定文本片段的技術(shù)。當(dāng)您需要在應(yīng)用程序中實(shí)現(xiàn)全文本搜索時(shí),可以使用這兩個(gè)注解來創(chuàng)建虛擬表。

(1)@Fts3 注解

@Fts3 注解用于創(chuàng)建一個(gè)基于 SQLite FTS3 算法的虛擬表。例如:

@Fts3
@Entity(tableName = "books")
data class Book(
    @ColumnInfo(name = "book_title") val title: String,
    @ColumnInfo(name = "book_author") val author: String,
    @ColumnInfo(name = "book_description") val description: String
)

在這個(gè)例子中,我們使用 @Fts3 注解定義了一個(gè)名為 books 的虛擬表。該表將基于 title、authordescription 列的內(nèi)容創(chuàng)建一個(gè)全文本索引。當(dāng)您執(zhí)行全文本搜索時(shí),將使用該索引來查找與搜索查詢匹配的行。

(2)@Fts4 注解

@Fts4 注解用于創(chuàng)建一個(gè)基于 SQLite FTS4 算法的虛擬表。例如:

@Fts4(contentEntity = Book::class)
@Entity(tableName = "book_fts")
data class BookFts(
    @ColumnInfo(name = "book_fts_title") val title: String,
    @ColumnInfo(name = "book_fts_author") val author: String,
    @ColumnInfo(name = "book_fts_description") val description: String
)

在這個(gè)例子中,我們使用 @Fts4 注解定義了一個(gè)名為 book_fts 的虛擬表。該表將基于 title、authordescription 列的內(nèi)容創(chuàng)建一個(gè)全文本索引。與 @Fts3 注解不同的是,@Fts4 注解需要使用 contentEntity 參數(shù)指定要?jiǎng)?chuàng)建索引的實(shí)體類。

(3)使用全文本搜索

創(chuàng)建全文本搜索虛擬表后,您可以使用 Room 中的 MATCH 關(guān)鍵字來執(zhí)行全文本搜索。例如:

@Dao
interface BookDao {
    @Query("SELECT * FROM books WHERE books MATCH :query")
    fun searchBooks(query: String): List<Book>
}

在這個(gè)例子中,我們使用 MATCH 關(guān)鍵字來執(zhí)行全文本搜索操作。該操作將在 books 虛擬表中搜索與 query 參數(shù)匹配的行,并返回所有匹配的結(jié)果。注意,在使用這些注解時(shí),請(qǐng)確保為要搜索的列創(chuàng)建了索引,以避免搜索操作變得緩慢或不可用。

總結(jié)

我們?cè)谶@一篇提到了17個(gè)注釋,,我們可以使用以上注解來定義實(shí)體類、DAO接口和數(shù)據(jù)庫,并實(shí)現(xiàn)各種數(shù)據(jù)操作和類型轉(zhuǎn)換。這些注解可以幫助我們更好地使用Room進(jìn)行開發(fā),并實(shí)現(xiàn)更加復(fù)雜和高效的功能,涵蓋了絕大數(shù)開發(fā)的需求。當(dāng)然,在實(shí)際開發(fā)中,我們還需要根據(jù)具體的業(yè)務(wù)需求和技術(shù)特點(diǎn)來選擇合適的方案和實(shí)現(xiàn)方式。

實(shí)際上,Room的應(yīng)用遠(yuǎn)不止如此,如果有人感興趣的話,我就繼續(xù)出下一期吧!

感謝

  • 校稿:ChatGpt/Bing
  • 文筆優(yōu)化:ChatGpt/Bing/秘塔寫作貓

以上就是快速了解Android Room使用細(xì)則進(jìn)階的詳細(xì)內(nèi)容,更多關(guān)于Android Room使用細(xì)則的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論