Jetpack Room数据库
Jetpack Room数据库
简介
Room 在 SQLite 上提供了一个抽象层,以便在充分利用 SQLite 的强大功能的同时,能够流畅地访问数据库。
处理大量结构化数据的应用可极大地受益于在本地保留这些数据。最常见的用例是缓存相关数据。这样,当设备无法访问网络时,用户仍可在离线状态下浏览相应内容。设备重新连接到网络后,用户发起的所有内容更改都会同步到服务器。
由于 Room 负责为您处理这些问题,因此我们强烈建议您使用 Room(而不是SQLite)。
依赖(AndroidX环境下)
在kotlin中使用需要添加kapt插件,在app的build.gradle文件的最上方添加如下代码:
apply plugin: 'kotlin-kapt'
然后在app的build.gradle文件中添加如下代码:
dependencies {
......你的其他依赖
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扩展和协程对Room的支持
implementation "androidx.room:room-ktx:$room_version"
//可选-RxJava对Room的支持
implementation "androidx.room:room-rxjava2:$room_version"
//可选-Guava对Room的支持,包括Optional和ListenableFuture
implementation "androidx.room:room-guava:$room_version"
//可选-需要用到相关测试工具的话
testImplementation "androidx.room:room-testing:$room_version"
}
注意:避免出现Schema export directory is not provided警告,还需添加:
defaultConfig {
//指定room.schemaLocation生成的文件路径 处理Room 警告 Schema export Error
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
}
}
}
Entity 实体类
@Entity(tableName = "users",primaryKeys = ["user_name","user_age"])
data class User(
@PrimaryKey(autoGenerate = true) val id: Long,
@ColumnInfo(name = "user_name") val name: String,
@ColumnInfo(name = "user_age") val age: Int,
@ColumnInfo val onLine: Boolean,
@Ignore val remark: String
)
@Entity:定义表名、复合主键、索引等
- tableName:设置表名字。默认是类的名字。
- indices:设置索引。
- inheritSuperIndices:父类的索引是否会自动被当前类继承。
- primaryKeys:设置联合主键。
- foreignKeys:设置外键。
- ignoredColumns : 被忽略的字段。
@PrimaryKey:定义主键,autoGenerate设置是否自增
@ColumnInfo:定义字段名,name设置表中字段名,不设置默认为属性名
@Ignore:定义属性不被创建在表中
Dao 数据访问类
@Dao
interface UserDao {
//查询所有用户
@Query("select * from users")
fun getUsers(): List<User>
//根据ID查询用户
@Query("select * from users where id = :id")
fun getUserById(id: Long): User
//根据用户名模糊查询用户
@Query("select * from users where user_name Like '%' || :name ||'%'")
fun getUsersByName(name: String): List<User>
//根据用户名和年龄查询用户
@Query("select * from users where user_name =:name and user_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 users where id = :id")
fun deleteUserById(id: Long)
}
Database 单例数据库
@Database(entities = [User::class], version = 1)
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
}
}
}
entities:数据库相关的所有Entity实体类,他们会转化成数据库里面的表。
可以传多个。例如:entities = [User::class,User1::class]
version:数据库版本。
数据库升级
当我们更新数据库表结构或新增表数据的时候,我们需要保留现有的数据,这时,我们需要对数据库进行更新,Room 支持通过 Migration 类进行增量迁移,以满足此需求。
具体操作如下:
- 更新数据库版本
- 创建Migration
- 添加Migration到数据库
@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(MIGRATION_1_2)
.build()
}
return instance as AppDatabase
}
//给User表添加一个mobile字段
private val MIGRATION_1_2: Migration = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE User " + " ADD COLUMN mobile TEXT")
}
}
}
}
基本使用
val users = listOf(
User(1, "张三", 20, true, "123456", ""),
User(2, "李四", 22, true, "123456", "")
)
//插入
AppDatabase.getInstance(this)
.userDao()
.addUsers(users)
//查询
AppDatabase.getInstance(this)
.userDao()
.getUsers()
val updateUsers = listOf(
User(1, "张三1", 20, true, "123456", ""),
User(2, "李四2", 22, true, "123456", "")
)
//更新
AppDatabase.getInstance(this)
.userDao()
.updateUsers(updateUsers)
//删除
AppDatabase.getInstance(this)
.userDao()
.deleteUser(User(1, "张三1", 20, true, "123456", ""))
遇到的一些问题
-
编译警告 Incremental annotation processing requested
原因
这是 Kotlin 1.3.50 的 bug,自 1.3.31 起,kapt 支持增量注解处理
解决方法 -
版本降级
使用 1.3.41 或以下版本
-
禁用增量编译
在项目根目录下的 gradle.properties 文件中,
添加kapt.incremental.apt=false
-
编译警告 Schema export directory is not provided to the annotation
processor so we cannot export…
原因
没有指定room.schemaLocation生成的文件路径
解决办法 -
给RoomDatabase设置exportSchema注解为false
@Database(entities = [User::class], version = 2, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
- 指定room.schemaLocation生成的文件路径
defaultConfig {
//指定room.schemaLocation生成的文件路径 处理Room 警告 Schema export Error
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
}
}
}
上一篇: Promethus(普罗米修斯)监控Mysql数据库
下一篇: Lua脚本的加密压缩和解压缩
推荐阅读
-
Android 数据库之 Room(五)
-
Promethus(普罗米修斯)监控Mysql数据库
-
Jetpack Room数据库
-
嗖的一下!只要一条命令,K8s监控数据一键写入时序数据库 redismysql
-
使用JConsole监控c3p0的连接情况 博客分类: tomcatjava数据库 监控c3p0JConsolejmx
-
NoSQL数据库探讨之一 - 为什么要用非关系数据库?(转) 博客分类: 非关系型数据库 NoSQL数据结构CassandraRedisMongoDB
-
MongoDB运行状态、性能监控,分析 博客分类: 数据库nosql mongostatmongodb监控数据库
-
Java数据库连接池(三) JDBC连接池调优监控DBPoolTrace btrace
-
centos 数据库操作命令
-
数据库数据导入到excel,源代码 博客分类: java 数据库excel源代码