Jetpack Room数据库

Jetpack Room数据库

简介
Room 在 SQLite 上提供了一个抽象层,以便在充分利用 SQLite 的强大功能的同时,能够流畅地访问数据库。
处理大量结构化数据的应用可极大地受益于在本地保留这些数据。最常见的用例是缓存相关数据。这样,当设备无法访问网络时,用户仍可在离线状态下浏览相应内容。设备重新连接到网络后,用户发起的所有内容更改都会同步到服务器。
由于 Room 负责为您处理这些问题,因此我们强烈建议您使用 Room(而不是SQLite)。

Room架构图

依赖(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:数据库版本。

扫描二维码关注公众号,回复: 11430335 查看本文章

数据库升级
当我们更新数据库表结构或新增表数据的时候,我们需要保留现有的数据,这时,我们需要对数据库进行更新,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.版本降级

	使用 1.3.41 或以下版本

2.禁用增量编译

	在项目根目录下的 gradle.properties 文件中,
	添加 `kapt.incremental.apt=false`
  • 编译警告 Schema export directory is not provided to the annotation
    processor so we cannot export…

    原因
    没有指定room.schemaLocation生成的文件路径

    解决办法

1.给RoomDatabase设置exportSchema注解为false

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

2.指定room.schemaLocation生成的文件路径

defaultConfig {
    //指定room.schemaLocation生成的文件路径  处理Room 警告 Schema export Error
    javaCompileOptions {
        annotationProcessorOptions {
            arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
        }
    }
}

猜你喜欢

转载自blog.csdn.net/summerrse/article/details/107390106