一、對(duì)象關(guān)系映射 - ORM / Object Relational Mapping
Android 系統(tǒng)中使用的數(shù)據(jù)庫(kù)是 SQLite 關(guān)系型數(shù)據(jù)庫(kù) , 使用 Android 提供的 api 訪(fǎng)問(wèn) SQLite 數(shù)據(jù)庫(kù)非常繁瑣 , 由此出現(xiàn)了很多 ORM 框架 ;
ORM 英文全稱(chēng) Object Relational Mapping , 對(duì)象關(guān)系映射 ;
對(duì)象關(guān)系映射 ORM 是一種編程技術(shù) , 面向?qū)ο缶幊陶Z(yǔ)言 與 關(guān)系型數(shù)據(jù)庫(kù) 之間的 映射 ;
- 對(duì)象 指的是 面向?qū)ο缶幊陶Z(yǔ)言 ,
- 關(guān)系 指的是 關(guān)系型數(shù)據(jù)庫(kù) ;
借助 ORM 對(duì)象關(guān)系映射 框架 訪(fǎng)問(wèn)數(shù)據(jù)庫(kù) , 可以 簡(jiǎn)化數(shù)據(jù)庫(kù)操作流程 , 開(kāi)發(fā)人員使用面向?qū)ο?API 與 數(shù)據(jù)庫(kù)進(jìn)行交互 , 比編寫(xiě)復(fù)雜的 SQL 語(yǔ)句操作數(shù)據(jù)庫(kù) 要簡(jiǎn)單很多 ;
ORM 框架常使用 元數(shù)據(jù) 將 數(shù)據(jù)庫(kù)表 與 編程語(yǔ)言中的類(lèi) 進(jìn)行映射 , 數(shù)據(jù)庫(kù)表字段 與 類(lèi)中的字段 一一對(duì)應(yīng) , 常用的元數(shù)據(jù)有 :
- 注解
- 配置文件
ORM 框架優(yōu)點(diǎn) :
- 提高了開(kāi)發(fā)效率 : 使用 ORM 操作數(shù)據(jù)庫(kù) 簡(jiǎn)化了數(shù)據(jù)庫(kù)操作過(guò)程 , 令代碼更容易開(kāi)發(fā)維護(hù) ;
- 提高了可移植性 : 使用 ORM 框架操作數(shù)據(jù)庫(kù) , 可以在 不改變代碼的前提下 , 更換底層數(shù)據(jù)庫(kù) ;
- 提高了性能 : 可以 總體優(yōu)化 ORM 框架的 增刪查改 操作性能 ;
- 提高了安全性 : 可避免直接使用 SQL 語(yǔ)句查詢(xún)時(shí) , 產(chǎn)生的 SQL 注入攻擊 ;
常見(jiàn)的 ORM 框架 :
- Android 平臺(tái) : GreenDao / ORMLite ;
- JavaEE 平臺(tái) : Hibernate ;
- .NET 平臺(tái) : Entity Framework ;
- Python 平臺(tái) : DiangoORM ;
在 Android 中 , Google 官方提供了一個(gè)基于 SQLite 關(guān)系型數(shù)據(jù)庫(kù)操作封裝的 ORM 框架 , Room 框架 ;
二、Room 框架的組成部分
1、@Entity / @Dao / @Database 注解
Room 框架中的重要注解 :
@Entity 注解 : 用于修飾 JavaBean 實(shí)體類(lèi) , 對(duì)應(yīng)數(shù)據(jù)庫(kù)中的一張表結(jié)構(gòu) ;
@Dao 注解 : 用于修飾 數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)對(duì)象 類(lèi) , 其中定義了 數(shù)據(jù)庫(kù)的 增刪改查 函數(shù) ;
-
@Database 注解 :
修飾 數(shù)據(jù)庫(kù)持有者 , 數(shù)據(jù)庫(kù)持有者 就是 數(shù)據(jù)庫(kù)鏈接對(duì)象 , 是 應(yīng)用持久化數(shù)據(jù)底層連接的接入點(diǎn) ;
- 使用 @Database 注解 修飾的類(lèi) , 該類(lèi)必須繼承 RoomDatabase 抽象類(lèi) ;
- 在該注解中 , 需要定義 數(shù)據(jù)庫(kù) 相關(guān)的 實(shí)體類(lèi) 列表 ;
- 數(shù)據(jù)庫(kù)持有者 包含 沒(méi)有參數(shù)的抽象方法 , 該方法返回 Dao 對(duì)象 ;
2、Entity 實(shí)體類(lèi) / Dao 數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)對(duì)象 / Database 數(shù)據(jù)庫(kù)持有者 之間的關(guān)系
Database 數(shù)據(jù)庫(kù)持有者 , Dao ( Data Access Objects ) 數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)對(duì)象 , Entity 實(shí)體類(lèi) , 三者之間的關(guān)系如下 :
- 首先 , 在 Android 應(yīng)用中 , 通過(guò) Room 框架的 Database 拿到 數(shù)據(jù)庫(kù)持有者 對(duì)象 ;
- 然后 , 通過(guò) 數(shù)據(jù)庫(kù)持有者 Database 拿到 Dao ( Data Access Objects ) 數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)對(duì)象 ;
- 最后 , 通過(guò) Dao ( Data Access Objects ) 數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)對(duì)象 訪(fǎng)問(wèn) 數(shù)據(jù)庫(kù)中每個(gè)表對(duì)應(yīng)的 Entity 實(shí)體類(lèi)對(duì)象 ;

三、Room 框架使用步驟
Room 框架使用步驟 :
- 添加 Room 框架依賴(lài)
- 創(chuàng)建 Entity 實(shí)體類(lèi)
- 創(chuàng)建 Dao 實(shí)體類(lèi)
- 創(chuàng)建 RoomDatabase 數(shù)據(jù)庫(kù)實(shí)例對(duì)象
- 初始化 Room 數(shù)據(jù)庫(kù)
- 調(diào)用 Dao 執(zhí)行數(shù)據(jù)庫(kù)增刪改查操作
1、添加 Room 框架依賴(lài)
在 Module 模塊下的 build.gradle 構(gòu)建腳本 中 , 配置如下依賴(lài)項(xiàng) :
dependencies {
// 配置 Room 框架版本號(hào)
def room_version = "2.4.0"
// 核心運(yùn)行時(shí)依賴(lài)庫(kù) 在應(yīng)用運(yùn)行時(shí)提供 Room 框架的數(shù)據(jù)庫(kù)相關(guān)核心功能
implementation "androidx.room:room-runtime:$room_version"
// 編譯時(shí)依賴(lài)項(xiàng) 在編譯時(shí)實(shí)時(shí)生成 Room 代碼 如 : Dao 實(shí)現(xiàn)類(lèi) / AppDatabase 子類(lèi) / Entity 實(shí)體類(lèi)映射器
annotationProcessor "androidx.room:room-compiler:$room_version"
// 可選配置項(xiàng) - 支持 Kotlin 擴(kuò)展和協(xié)程的 Room 框架 如果使用的是 Kotlin 語(yǔ)言必須導(dǎo)入該依賴(lài)
implementation "androidx.room:room-ktx:$room_version"
}
androidx.room:room-runtime 依賴(lài)庫(kù) 是 運(yùn)行時(shí)核心依賴(lài)庫(kù) , 在應(yīng)用運(yùn)行時(shí)提供 Room 框架的數(shù)據(jù)庫(kù)相關(guān)核心功能 ; 該依賴(lài)庫(kù) 包含了 Room 持久化庫(kù)的核心功能 , 如 :
- RoomDatabase 類(lèi):用于表示數(shù)據(jù)庫(kù),可以包含一個(gè)或多個(gè)表,并提供了一些方法來(lái)操作數(shù)據(jù)庫(kù),例如插入、刪除和查詢(xún)數(shù)據(jù)等。
- Entity 注解:用于標(biāo)記實(shí)體類(lèi),指定實(shí)體類(lèi)對(duì)應(yīng)的數(shù)據(jù)庫(kù)表的名稱(chēng)和字段信息等。
- Dao 數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)對(duì)象:用于定義訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的方法,例如查詢(xún)、插入和刪除等操作。
- Query 注解:用于標(biāo)記 DAO 接口中的方法,并指定 SQL 查詢(xún)語(yǔ)句。
- PrimaryKey 注解:用于指定實(shí)體類(lèi)中的主鍵字段。
- TypeConverters 注解:用于標(biāo)記類(lèi)型轉(zhuǎn)換器類(lèi),將特定類(lèi)型的數(shù)據(jù)轉(zhuǎn)換為數(shù)據(jù)庫(kù)中的原生類(lèi)型。
androidx.room:room-compiler 依賴(lài)庫(kù) 是 Room 持久化庫(kù)中的一個(gè) 編譯時(shí)依賴(lài)項(xiàng) , 用于 在編譯時(shí)生成 Room 的如下實(shí)現(xiàn)代碼 :
- AppDatabase 的子類(lèi) , 用于創(chuàng)建和訪(fǎng)問(wèn)數(shù)據(jù)庫(kù) ;
- Dao 數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)對(duì)象實(shí)現(xiàn)類(lèi) , 用于執(zhí)行 SQL 查詢(xún)和操作 ;
- 實(shí)體類(lèi) Entity 的映射器 , 用于將數(shù)據(jù)庫(kù)中的數(shù)據(jù)映射到實(shí)體類(lèi)中 ;
androidx.room:room-ktx 依賴(lài)庫(kù) , 提供了 Kotlin 擴(kuò)展功能 , 如果使用的是 Kotlin 語(yǔ)言 , 則必須導(dǎo)入該依賴(lài)庫(kù) ;
2、創(chuàng)建 Entity 實(shí)體類(lèi)
創(chuàng)建 Entity 實(shí)體類(lèi) , 該實(shí)體類(lèi)對(duì)應(yīng)著數(shù)據(jù)庫(kù)中的一張表 , 需要使用如下注解修飾
- 使用 @Entity 注解修飾實(shí)體類(lèi) , 并指定 數(shù)據(jù)庫(kù)表名 ;
- 使用 @PrimaryKey 注解修飾主鍵值 ,
- 使用 @ColumnInfo 注解修飾 數(shù)據(jù)庫(kù)表 列名 對(duì)應(yīng)的字段 ;
@Entity(tableName = "users")
data class User(
@PrimaryKey val id: Int,
@ColumnInfo(name = "name") val name: String,
@ColumnInfo(name = "age") val age: Int
)
3、創(chuàng)建 Dao 實(shí)體類(lèi)
創(chuàng)建 Dao 實(shí)體類(lèi) : 創(chuàng)建用于訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的 DAO 接口 , 并使用注解指定 SQL 查詢(xún)語(yǔ)句等信息 ;
- 使用 @Dao 注解修飾整個(gè) Dao 實(shí)體類(lèi) ;
- 使用 @Query 注解修飾查詢(xún)函數(shù) ;
- 使用 @Insert 注解修飾插入函數(shù) ;
- 使用 @Delete 注解修飾刪除函數(shù) ;
@Dao
interface UserDao {
@Query("SELECT * FROM users")
fun getAll(): List<User>
@Insert
fun insert(user: User)
@Delete
fun delete(user: User)
}
4、創(chuàng)建 RoomDatabase 數(shù)據(jù)庫(kù)實(shí)例對(duì)象
創(chuàng)建 RoomDatabase 數(shù)據(jù)庫(kù)實(shí)例對(duì)象 : 創(chuàng)建 RoomDatabase 的子類(lèi)實(shí)例對(duì)象 , 并定義抽象方法以獲取 DAO 實(shí)例 ;
@Database(entities = arrayOf(User::class), version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
5、初始化 Room 數(shù)據(jù)庫(kù)
初始化數(shù)據(jù)庫(kù) : 在應(yīng)用程序中使用 Room 數(shù)據(jù)庫(kù)之前 , 必須先創(chuàng)建數(shù)據(jù)庫(kù)實(shí)例 ;
val db = Room.databaseBuilder(
applicationContext,
AppDatabase::class.java, "database-name"
).build()
6、調(diào)用 Dao 執(zhí)行數(shù)據(jù)庫(kù)增刪改查操作
調(diào)用 Dao 執(zhí)行數(shù)據(jù)庫(kù)增刪改查操作 :
db.userDao().insert(User(1, "John", 25))
val users = db.userDao().getAll()