- Room是一個(gè)對(duì)象關(guān)系映射模型(ORM)用來操作Android自帶的SQLite數(shù)據(jù)庫的一個(gè)庫,主要是為了簡化訪問Android本地?cái)?shù)據(jù)庫。
- 框架由三個(gè)部分組成:Database、Entity、Dao
Database
Database就是代表著數(shù)據(jù)庫,內(nèi)部有一張張的表。
定一個(gè)數(shù)據(jù)庫
@Database(entities = [User.class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
- 定義一個(gè)抽象類,必須繼承自RoomDatabase
- 抽象類使用
@DataBase注解標(biāo)記 -
@DataBase注解中entities屬性定義了該數(shù)據(jù)庫擁有的表有哪些,version定義了數(shù)據(jù)庫的版本 - 抽象類中定義了無參的抽象方法,返回一個(gè)Dao對(duì)象(用于操作數(shù)據(jù)庫中表)
Database在定義的時(shí)候上面還可以用@TypeConverters注解,用于將某個(gè)類型轉(zhuǎn)換成數(shù)據(jù)庫能夠存儲(chǔ)的類型,例如將某個(gè)實(shí)體類序列化轉(zhuǎn)成String類型存到數(shù)據(jù)庫,取的時(shí)候再反序列化
創(chuàng)建數(shù)據(jù)庫
mAppDatabase = Room.databaseBuilder(getApplicationContext(), AppDatabase::class.java, "app.db")
.build();
創(chuàng)建數(shù)據(jù)庫的時(shí)候采用Room提供的Builder方法進(jìn)行創(chuàng)建,就可以拿到數(shù)據(jù)庫的引用。創(chuàng)建數(shù)據(jù)庫最好設(shè)計(jì)成單例,全局只初始化一次。
數(shù)據(jù)庫升級(jí)
mAppDatabase = Room.databaseBuilder(getApplicationContext(), AppDatabase::class.java, "app.db")
.addMigrations(MIGRATION_1_2)
.build();
/**
* 數(shù)據(jù)庫版本 1->2 user表格新增了age列
*/
private val MIGRATION_1_2: Migration = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
atabase.execSQL("ALTER TABLE User ADD COLUMN age integer")
}
}
迭代的過程中升級(jí)Android本地?cái)?shù)據(jù)庫正確的做法是,在上面的@DataBase注解中升級(jí)version屬性的版本號(hào),同時(shí)在創(chuàng)建DB的實(shí)例的時(shí)候調(diào)用addMigrationsapi提供Migration實(shí)例進(jìn)行數(shù)據(jù)遷移。
Entity
每個(gè)Entity類代表了數(shù)據(jù)庫中的一張表,Entity的每個(gè)字段對(duì)應(yīng)的是數(shù)據(jù)庫中的一列
@Entity(tableName = "user_info")
data class User {
@PrimaryKey
var id = 0
var firstName: String? = null
var lastName: String? = null
}
- 類用
@Entity注解標(biāo)記,tableName定義對(duì)應(yīng)的表的表名 -
@PrimaryKey標(biāo)識(shí)字段對(duì)應(yīng)的列作為主鍵
Dao
dao層定義這操作數(shù)據(jù)庫中表的CRUD的操作,注解標(biāo)識(shí)的方法Room會(huì)自動(dòng)生成該方法的一個(gè)實(shí)現(xiàn)進(jìn)行數(shù)據(jù)庫表的操作。
@Insert
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(user: User)
onConflict屬性有5個(gè)枚舉的取值
- OnConflictStrategy.REPLACE:沖突時(shí)取代舊數(shù)據(jù)同時(shí)繼續(xù)事務(wù)
- OnConflictStrategy.ROLLBACK:沖突時(shí)是回滾事務(wù)
- OnConflictStrategy.ABORT:沖突時(shí)終止事務(wù)
- OnConflictStrategy.FAIL:沖突時(shí)事務(wù)失敗
- OnConflictStrategy.IGNORE:沖突時(shí)忽略沖突
@Update
@Update(onConflict = OnConflictStrategy.REPLACE)
suspend fun updateUsers(vararg users: User)
Room會(huì)根據(jù)傳進(jìn)來的User的主鍵定義的值去匹配數(shù)據(jù)庫表中的數(shù)據(jù)去更新對(duì)應(yīng)的數(shù)據(jù)。
@Delete
@Delete(onConflict = OnConflictStrategy.REPLACE)
suspend fun deleteUsers(vararg users: User)
同樣Room會(huì)根據(jù)傳進(jìn)來的User的主鍵定義的值去匹配數(shù)據(jù)庫表中的數(shù)據(jù)去刪除對(duì)應(yīng)的數(shù)據(jù)。
@Query
@Query("SELECT * FROM user_info")
suspend fun queryAll(): List<User>
@Query("SELECT * FROM user_info WHERE firstName == :name")
suspend fun queryUsersByFirstName(name: String): List<User>
同時(shí)也可以將數(shù)據(jù)返回成LiveData提供上層進(jìn)行監(jiān)聽。
@Query("SELECT * FROM user_info")
suspend fun queryAll(): LiveData<List<User>>