• Andoird使用Room实现持久化及使用Room进行增删查改



    这篇文章会告诉你如何在Android中通过kotlin或者Java来实现数据持久化

    Room概述

    处理大量结构化数据的应用可极大地受益于在本地保留这些数据。最常见的使用场景是缓存相关的数据,这样一来,当设备无法访问网络时,用户仍然可以在离线状态下浏览该内容。

    Room 持久性库在 SQLite 上提供了一个抽象层,以便在充分利用 SQLite 的强大功能的同时,能够流畅地访问数据库。具体来说,Room 具有以下优势:

    • 提供针对 SQL 查询的编译时验证。
    • 提供方便注解,可最大限度减少重复和容易出错的样板代码。
    • 简化了数据库迁移路径。

    Room 包含三个主要组件:

    • 数据库类,用于保存数据库并作为应用持久性数据底层连接的主要访问点。
    • 数据实体,用于表示应用的数据库中的表。
    • 数据访问对象(DAO),为您的应用提供在数据库中查询、更新、插入和删除数据的方法。

    数据库类为应用提供与该数据库关联的 DAO 的实例。反过来,应用可以使用 DAO 从数据库中检索数据,作为关联的数据实体对象的实例。此外,应用还可以使用定义的数据实体更新相应表中的行,或者创建新行供插入。图 1 说明了 Room 的不同组件之间的关系。

    在这里插入图片描述

    Room的使用

    一、在gradle.build中添加依赖库

    kotlin

    需要先在build.gradle.kts中添加kapt插件

    • build.gradle(app)
    alias(libs.plugins.jetbrainsKotlinKapt)
    
    • 1
    • 项目的build.gradle.kts中也需要添加
    plugins {
        alias(libs.plugins.jetbrainsKotlinKapt) apply false
    }
    
    • 1
    • 2
    • 3

    然后再app的gradle中添加如下依赖

        //room依赖
        val room_version = "2.6.1"
        implementation("androidx.room:room-runtime:$room_version")
        // To use Kotlin annotation processing tool (kapt)
        kapt("androidx.room:room-compiler:$room_version")
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Java

    添加插件:

    plugins {
        id 'org.jetbrains.kotlin.kapt'
    }
    
    • 1
    • 2
    • 3

    添加依赖:

        def room_version = "2.6.1"
    
        implementation "androidx.room:room-runtime:$room_version"
        annotationProcessor "androidx.room:room-compiler:$room_version"
    
        // To use Kotlin annotation processing tool (kapt)
        kapt "androidx.room:room-compiler:$room_version"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    创建实体类

    1.创建User实体类

    @Entity(tableName = "user2")
    data class User(
            @ColumnInfo(name = "username")
            var userName: String? = null,
            @ColumnInfo(name = "password")
            var userPassword: String? = null
            ) {
    
            @PrimaryKey(autoGenerate = true)
            @ColumnInfo(name = "id")
            var id: Int = 0
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.添加注解:

    • 默认情况下,Room 将类名称用作数据库表名称。如果您希望表具有不同的名称,请设置 @Entity 注解的 tableName 属性。
    • Room 默认使用字段名称作为数据库中的列名称。如果您希望列具有不同的名称,请将 @ColumnInfo 注解添加到该字段并设置 name
      属性。
    • 每个 Room 实体都必须定义一个主键,用于唯一标识相应数据库表中的每一行。执行此操作的最直接方式是使用 @PrimaryKey
      为单个列添加注解(注意:如果您需要 Room 为实体实例分配自动 ID,请将 @PrimaryKey 的 autoGenerate
      属性设为 true。)
    • 默认情况下,Room 会为实体中定义的每个字段创建一个列。 如果某个实体中有您不想保留的字段,则可以使用 @Ignore
      为这些字段添加注解
      在这里插入图片描述

    创建抽象Dao层接口

    interface UserDao {
        @Query("SELECT * FROM user2")
        fun getAll(): List<User>
    
        @Delete
        fun delete(user: User)
    
        @Update
        fun updateUsers(vararg users: User)
    	
    	//这个注解表示如果数据已在数据库中存在增进行替换
        @Insert(onConflict = OnConflictStrategy.REPLACE)
        fun insert(users: List<User>)
    
        @Insert(onConflict = OnConflictStrategy.REPLACE)
        fun insert(user: User)
        //返回User的id值,判断是否添加成功
        @Insert(onConflict = OnConflictStrategy.REPLACE)
        fun insertReturnId(user: User) : Long
    
        @Query("SELECT * FROM user2 WHERE username = :userName AND password = :userPassword")
        fun queryUser(userName: String, userPassword: String): User?
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    创建DataBase层

    这里通过单例双重验证进行创建

    //这里exportSchema
    @Database(entities = [User::class], version = 1, exportSchema = false)
    abstract class UserDataBase : RoomDatabase() {
        companion object {
            private var instance: UserDataBase? = null
    
            fun getInstance(context: Context): UserDataBase? {
                if (instance == null) {
                    synchronized(Companion::class.java) {
                        if(null == instance) {
                            instance = Room.databaseBuilder(context, UserDataBase::class.java, "user.db")
                                    .addMigrations()
                                    .allowMainThreadQueries()//表示允许在主线程中进行数据库的操作
                                    .build()
                        }
                    }
                }
                return instance
            }
        }
        abstract fun getUserDao(): UserDao
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    注:可能会报 Schema export directory is not provided to the annotation processor异常
    有两种方式解决:
    1.在Database注解中添加 exportSchema = false
    2.在app的build.gradle中的defaultConfig下添加以下配置

    javaCompileOptions {
        annotationProcessorOptions {
            arrayOf("room.schemaLocation" to "$projectDir/schemas")
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 该类必须带有 @Database 注解,该注解包含列出所有与数据库关联的数据实体的 entities 数组。
    • 该类必须是一个抽象类,用于扩展 RoomDatabase。
    • 对于与数据库关联的每个 DAO 类,数据库类必须定义一个具有零参数的抽象方法,并返回 DAO 类的实例。

    使用创建的

     val userDataBase = UserDataBase.getInstance(this)
    
    //在子线程中去运行
     userDataBase?.runInTransaction {
    	val userDao: UserDao = db.userDao()
        val users = userDao.getAll()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    查看数据库

    通过Android Studio自带的工具就能够查看
    在这里插入图片描述
    或者在Device Explorer中的data/data/包名下的databases目录中,将db文件拉出来用其他数据库工具查看
    在这里插入图片描述

    总结:

    Room基本用法已经讲完了,更多详细内容请看 官方文档:https://developer.android.google.cn/training/data-storage/room?hl=zh-cn#groovy
    像数据库持久化的其他开源框架还有LitPal等
    LitePal介绍
    参考文章:
    Android-第十三节04Room框架详解

    Room 的引入及使用

  • 相关阅读:
    CSS 外边距、填充、分组嵌套、尺寸
    4 线程创建新增方式(JKD 5.0)
    用form表单以post的方式提交数据跳转地址
    前端面试:CSS常问
    雷军在微博发文:小米澎湃 OS(Xiaomi HyperOS)正式版已完成封包
    力扣 -- 873. 最长的斐波那契子序列的长度
    【(C语言)数据结构奋斗100天】顺序表和链表
    python系列教程184——尽量少用全局变量
    代码模版-实现form表单输入框和label统一对齐,vue+elementui
    机器人内部传感器阅读梳理及心得-速度传感器-模拟式速度传感器
  • 原文地址:https://blog.csdn.net/qq_44023485/article/details/139201777