Jetpack 总结系列- Google-Room数据库使用
Posted ZhangQiang-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jetpack 总结系列- Google-Room数据库使用相关的知识,希望对你有一定的参考价值。
官方文档 : Room 谷歌实验室:官方教程 SQL语法:SQLite教程
与greendao的区别:同样基于ORM模式封装的数据库。而Room和其他ORM对比,具有编译时验证查询语句正常性,支持LiveData数据返回等优势。
第一步 添加依赖
apply plugin: 'kotlin-kapt'
dependencies
// Room
implementation "androidx.room:room-runtime:2.2.5"
kapt "androidx.room:room-compiler:2.2.5"
androidTestImplementation "androidx.room:room-testing:$rootProject.roomVersion"
//注意:对于基于 Kotlin 的应用,请确保使用 kapt,而不是 annotationProcessor。您还应添加 kotlin-kapt 插件。
//注意:对于基于 Kotlin 的应用,请确保使用 kapt,而不是 annotationProcessor。您还应添加 kotlin-kapt 插件。
配置编译器选项
defaultConfig
//指定room.schemaLocation生成的文件路径 处理Room 警告 Schema export Error
javaCompileOptions
annotationProcessorOptions
arguments = [
//配置并启用将数据库架构导出到给定目录中的 JSON 文件的功能。如需了解详情,请参阅 Room 迁移。
"room.schemaLocation" : "$projectDir/schemas".toString(),
"room.incremental" : "true",//启用 Gradle 增量注释处理器
"room.expandProjection": "true"]//配置 Room 以重写查询
第二步 创建表(实体)
注解 | 说明 |
@Entity | 声明这是一个表(实体),主要参数:tableName-表名、foreignKeys-外键、indices-索引。 |
@ColumnInfo | 主要用来修改在数据库中的字段名。 @ColumnInfo(name = "shoe_id") |
@PrimaryKey | 声明该字段主键并可以声明是否自动创建。 @PrimaryKey(autoGenerate = true) |
@Ignore | 声明某个字段只是临时用,不存储在数据库中。 |
@Embedded | 用于嵌套,里面的字段同样会存储在数据库中。 |
@ForeignKey
| 外键约束 |
@Entity(tableName = "xxx")
@Entity(tableName = "xxx")
data class User(
@PrimaryKey val uid: Int,
@ColumnInfo(name = "first_name") val firstName: String?,
@ColumnInfo(name = "last_name") val lastName: String?
)
/** 示例
* 鞋表
*/@Entity(tableName = "shoe")data class Shoe(
@ColumnInfo(name = "shoe_name") val name: String // 鞋名
, @ColumnInfo(name = "shoe_description") val description: String// 描述
, @ColumnInfo(name = "shoe_price") val price: Float // 价格
, @ColumnInfo(name = "shoe_brand") val brand: String // 品牌
, @ColumnInfo(name = "shoe_imgUrl") val imageUrl: String // 图片地址)
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
var id: Long = 0
第三步 创建Dao
@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 " +
"last_name LIKE :last LIMIT 1")
fun findByName(first: String, last: String): User
@Insert
fun insertAll(vararg users: User)
@Delete
fun delete(user: User)
示例:
增 @Insert注解声明当前的方法为新增的方法,并且可以设置当新增冲突的时候处理的方法。 @Insert(onConflict = OnConflictStrategy.REPLACE)主键相同的话,旧数据会替换新数据。 @Daointerface ShoeDao // 省略... // 增加一双鞋子 @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertShoe(shoe: Shoe) // 增加多双鞋子 // 除了List之外,也可以使用数组 @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertShoes(shoes: List<Shoe>) | 查 Room的查很接近原生的SQL语句。@Query注解不仅可以声明这是一个查询语句,也可以用来删除和修改,不可以用来新增。
简单查询 查询多个的时候,可以返回List和数组,还可以配合LiveData和RxJava 2。 @Daointerface ShoeDao // 查询一个 @Query("SELECT * FROM shoe WHERE id=:id") fun findShoeById(id: Long): Shoe? // 查询多个 通过品牌查询多款鞋 @Query("SELECT * FROM shoe WHERE shoe_brand=:brand") fun findShoesByBrand(brand: String): List<Shoe> // 模糊查询 排序 同名鞋名查询鞋 @Query("SELECT * FROM shoe WHERE shoe_name LIKE :name ORDER BY shoe_brand ASC") fun findShoesByName(name:String):List<Shoe> // 配合LiveData 返回所有的鞋子 @Query("SELECT * FROM shoe") fun getAllShoesLD(): LiveData<List<Shoe>> // 配合LiveData 通过Id查询单款鞋子 @Query("SELECT * FROM shoe WHERE id=:id") fun findShoeByIdLD(id: Long): LiveData<Shoe> // 配合RxJava 通过Id查询单款鞋子 @Query("SELECT * FROM shoe WHERE id=:id") fun findShoeByIdRx(id: Long): Flowable<Shoe> // 省略...
复合查询 @Daointerface ShoeDao // 省略... // 根据收藏结合 查询用户喜欢的鞋的集合 内联查询 @Query( "SELECT shoe.id,shoe.shoe_name,shoe.shoe_description,shoe.shoe_price,shoe.shoe_brand,shoe.shoe_imgUrl " + "FROM shoe " + "INNER JOIN fav_shoe ON fav_shoe.shoe_id = shoe.id " + "WHERE fav_shoe.user_id = :userId" ) fun findShoesByUserId(userId: Long): LiveData<List<Shoe>>
|
删 @Delete注解声明当前的方法是一个删除方法。 @Daointerface ShoeDao // 省略... // 删除一双鞋子 @Delete fun deleteShoe(shoe: Shoe) // 删除多个鞋子 // 参数也可以使用数组 @Delete fun deleteShoes(shoes:List<Shoe>) | |
改 @Update注解声明当前方法是一个更新方法 @Daointerface ShoeDao // 省略... // 更新一双鞋 @Update fun updateShoe(shoe:Shoe) // 更新多双鞋 // 参数也可以是集合 @Update fun updateShoes(shoes:Array<Shoe>)
更新部分字段: @Query("UPDATE people SET is_alive= :alive WHERE name = :name") public abstract int setIsAliveByName(String name, int alive); |
第四步 创建数据库
/**
* 数据库文件
*/@Database(entities = [User::class,Shoe::class,FavouriteShoe::class],version = 1,exportSchema = false)abstract class AppDataBase:RoomDatabase()
// 得到UserDao
abstract fun userDao():UserDao
// 得到ShoeDao
abstract fun shoeDao():ShoeDao
// 得到FavouriteShoeDao
abstract fun favouriteShoeDao():FavouriteShoeDao
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,"jetPackDemo-database")
.addCallback(object :RoomDatabase.Callback()
override fun onCreate(db: SupportSQLiteDatabase)
super.onCreate(db)
// 读取鞋的集合
val request = OneTimeWorkRequestBuilder<ShoeWorker>().build()
WorkManager.getInstance(context).enqueue(request)
)
.build()
@Database注解声明当前是一个数据库文件,注解中entities变量声明数据库中的表(实体),以及其他的例如版本等变量。同时,获取的Dao也必须在数据库类中。完成之后,点击build目录下的make project,系统就会自动帮我创建AppDataBase和xxxDao的实现类。
第五步 简要封装
在不使用LiveData和RxJava的前提下,Room的操作是不可以放在主线程中的。
/**
* 用户处理仓库
*/class UserRepository private constructor(private val userDao: UserDao)
//...
/**
* 登录用户 本地数据库的查询
*/
fun login(account: String, pwd: String):LiveData<User?>
= userDao.login(account,pwd)
/**
* 注册一个用户 本地数据库的新增
*/
suspend fun register(email: String, account: String, pwd: String):Long
return withContext(IO)
userDao.insertUser(User(account, pwd, email))
companion object
@Volatile
private var instance: UserRepository? = null
fun getInstance(userDao: UserDao): UserRepository =
// ...
register()方法是一个普通方法,所以它需要在子线程使用,如代码所见,通过协程实现。login()是配合LiveData使用的,不需要额外创建子线程,但是他的核心数据库操作还是在子线程中实现的。
参考:
Google文档 ; Room库版本 ; SQLite教程0-菜鸟
Android从零开始搭建MVVM架构(4)————Room(从入门到进阶)
Room数据库迁移 ; Room数据库升级(知乎) ; Room数据库版本升级,数据迁移详解 ; Room数据库的版本升级姿势
以上是关于Jetpack 总结系列- Google-Room数据库使用的主要内容,如果未能解决你的问题,请参考以下文章
Jetpack Compose - animateXxxAsState