尚拙

一个分享技术、学习成长的个人博客网站

0%

Jetpack架构组件之Room

Room是Google推出的Android架构组件库中的数据持久化组件库, 也可以说是在SQLite上实现的一套ORM解决方案。

一、简介

Room是Google提供的一个ORM库。Room提供了三个主要的组件:

Entity:实体类,对应的是数据库的一张表结构。需要使用注解 @Entity 标记。

Dao:包含访问一系列访问数据库的方法。需要使用注解 @Dao 标记。

Database:数据库持有者,作为与应用持久化相关数据的底层连接的主要接入点。需要使用注解 @Database 标记。 使用@Database注解需满足以下条件: 定义的类必须是一个继承于RoomDatabase的抽象类。 在注解中需要定义与数据库相关联的实体类列表。 包含一个没有参数的抽象方法并且返回一个带有注解的 @Dao。

二、基本使用

1、添加依赖

def room_version = "2.2.5"
implementation "androidx.room:room-runtime:$room_version"
//kotlin下使用
kapt "androidx.room:room-compiler:$room_version"
//java下使用
annotationProcessor "androidx.room:room-compiler:$room_version"

在kotlin中使用需要添加kapt插件,在app的build.gradle文件的最上方添加如下代码:

apply plugin: 'kotlin-kapt'

2、Entity 实体类配置

使用@Entity注解实体类

@Entity
data class User(
@PrimaryKey(autoGenerate = true) var id: Long,
var name: String,
var age: Int,
var onLine: Boolean,
@Ignore var remark: String,
var mobile:String
){
constructor() : this(0,"",0,false,"","")
}

注解说明:

@Entity:定义表名、复合主键、索引等

tableName:设置表名字。默认是类的名字。

indices:设置索引。

inheritSuperIndices:父类的索引是否会自动被当前类继承。

primaryKeys:设置联合主键。

foreignKeys:设置外键。

ignoredColumns : 被忽略的字段。

@PrimaryKey:定义主键,autoGenerate设置是否自增

@ColumnInfo:定义字段名,name设置表中字段名,不设置默认为属性名

@Ignore:定义属性不被创建在表中

3、创建 Dao 数据访问类

Dao类是一个 interface,其中定义了一系列的操作数据库的方法。通常我们操作数据库无非就是增删改查。Room也为我们的提供了相关的注解,有@Insert、@Delete、@Update 和 @Query。

@Dao
interface UserDao {
//查询所有用户
@Query("select * from user")
fun getUsers(): List<User>

//根据ID查询用户
@Query("select * from user where id = :id")
fun getUserById(id: Long): User

//根据用户名模糊查询用户
@Query("select * from user where name Like '%' || :name ||'%'")
fun getUsersByName(name: String): List<User>

//根据用户名和年龄查询用户
@Query("select * from user where name =:name and age >:age")
fun getUsersByNameAndAge(name: String, age: Int): List<User>

//插入用户
/*
onConflict:默认值是OnConflictStrategy.ABORT,表示当插入有冲突的时候的处理策略。
OnConflictStrategy封装了Room解决冲突的相关策略:
1. OnConflictStrategy.REPLACE:冲突策略是取代旧数据同时继续事务。
2. OnConflictStrategy.ROLLBACK:冲突策略是回滚事务。
3. OnConflictStrategy.ABORT:冲突策略是终止事务。
4. OnConflictStrategy.FAIL:冲突策略是事务失败。
5. OnConflictStrategy.IGNORE:冲突策略是忽略冲突。
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun addUsers(users: List<User>)

//更新用户
@Update
fun updateUsers(users: List<User>)

//删除用户
@Delete
fun deleteUser(user: User)

//根据条件删除用户
@Query("delete from user where id = :id")
fun deleteUserById(id: Long)

}

4、创建 Database 单例数据库

@Database(entities = [User::class], version = 2)
abstract class AppDatabase : RoomDatabase() {

abstract fun userDao(): UserDao

companion object {
private var instance: AppDatabase? = null
fun getInstance(context: Context): AppDatabase {
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"data.db"
).allowMainThreadQueries()
.build()
}
return instance as AppDatabase
}
}
}

5、使用

val users = listOf(
User(1, "张三", 20, true, "123456","45454"),
User(2, "李四", 22, true, "123456","45454")
)

AppDatabase.getInstance(this).userDao().addUsers(users)

var userList = AppDatabase.getInstance(this)
.userDao()
.getUsers()

6、数据库升级

1、修改版本号

2、调用addMigrations方法,其中Migration需要两个参数,startVersion表示的是升级开始的版本,endVersion表示要升级到的版本。同时需要将@Database注解中的version的值修改为和endVersion相同。

@Database(entities = [User::class], version = 2)
abstract class AppDatabase : RoomDatabase() {

abstract fun userDao(): UserDao

companion object {
private var instance: AppDatabase? = null
fun getInstance(context: Context): AppDatabase {
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"data.db"
).allowMainThreadQueries()
.addMigrations(object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE User ADD COLUMN mobile TEXT NOT NULL DEFAULT 10")
}
})
.build()
}
return instance as AppDatabase
}
}
}