IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Room数据库使用与踩坑(最新) -> 正文阅读

[移动开发]Room数据库使用与踩坑(最新)

目录

一、介绍

关于Room数据库的介绍可以看Android官方的(使用 Room 将数据保存到本地数据库 ?|? Android 开发者 ?|? Android Developers),这里主要介绍一些官方缺少的和一些踩坑。

二、引入

如需在应用中使用 Room,请将以下依赖项添加到应用的?build.gradle?文件:
注意:Room的版本号与kotlin的版本号需要对应

dependencies {

    implementation "org.jetbrains.kotlin:kotlin-stdlib:1.3.72"
    implementation 'androidx.core:core-ktx:1.3.2'

    def latest_version = "2.2.5"
    //room
    implementation "androidx.room:room-runtime:$latest_version"
    implementation "androidx.room:room-ktx:$latest_version"
    kapt "androidx.room:room-compiler:$latest_version"
    // optional - 支持Rxjava2与Room
    implementation "androidx.room:room-rxjava2:$latest_version"

    // optional - 支持协程与Room
    implementation("androidx.room:room-ktx:$latest_version")

}

三、使用(增删改查)

使用前需要先准备数据实体,数据访问对象(DAO),数据库

数据实体

@Entity
class RunRecord {
    @PrimaryKey(autoGenerate = true)
    var id: Long? = null

    @ColumnInfo(name = "userId")
    var userId: String? = null

    @ColumnInfo(name = "pathLine")
    var pathLine: String? = null

    @ColumnInfo(name = "totalStep")
    var totalStep:Int? = 0
}

数据访问对象

注意:返回主键ID类型与数据实体中的主键类型对应。或者实体中的类型是Int,插入成功返回Long/Int,不能相反。

@Dao
interface RunDao {

    /**
     *
     * 插入一条信息,id不用传,会自动增长.建议不传
     * @return Long  返回插入的主键id
     */
    @Insert
    fun insert(info: RunRecord?): Long

    @Query("INSERT into RunRecord(userId,pathLine) values(:userId,:pathLine) ")
    fun insert(userId: String?, pathLine: String?): Long

    /**
     * @return Int  1 成功 0失败
     */
    @Delete
    fun delete(info: RunRecord?): Int

    @Query("DELETE FROM RunRecord WHERE userId = :userId")
    fun delete(userId: String?): Int

    /**
     * @return Int 返回删除的条数
     */
    @Query("DELETE FROM RunRecord")
    fun deleteAll(): Int

    /**
     * @return Int  1 成功 0失败
     */
    @Update
    fun update(vararg info: RunRecord?): Int

    @Query("UPDATE RunRecord SET pathLine =:info WHERE userId = :userId")
    fun updateRunInfo(userId: String, info: String): Int

    /**
     * 根据userId获取最后一条
     */
    @Query("SELECT * FROM RunRecord WHERE userId LIKE :userId order by userId desc  LIMIT 1")
    fun findLastByUserId(userId: String): RunRecord?

    /**
     * 查询全部数据
     */
    @get:Query("SELECT * FROM RunRecord")
    val all: List<RunRecord?>?
}

数据库

@Database(entities = [ RunRecord::class], version = 1)
abstract class YzDatabase : RoomDatabase() {
    abstract fun runDao(): RunDao?

    companion object {
        private const val DB_NAME = "yzWill.db"

        @Volatile
        private var instance: YzDatabase? = null
        fun getInstance(context: Context) =
            instance ?: synchronized(this) {
                instance ?: Room.databaseBuilder(
                    context,
                    YzDatabase::class.java, DB_NAME
                ).build()
            }
    }
}

注意:Room的操作都需要在子线程执行,如果需要在主线程执行需要设置allowMainThreadQueries()方法

如下设置:

fun getInstance(context: Context) =
    instance ?: synchronized(this) {
        instance ?: Room.databaseBuilder(
            context,
            YzDatabase::class.java, DB_NAME
        ).allowMainThreadQueries().build()
    }

3.1 增

插入一条数据,返回主键ID,初始也就是1

@Insert用法

val db = YzDatabase.getInstance(this).runDao()
Thread() {
    //插入一条数据,返回主键id
    val id = db?.insert(RunRecord().apply {
        pathLine = "插入一条信息"
        userId = "小小虫"
    })
    Log.e(tag, "id:$id")
}.start()

@Query("INSERT into RunRecord(userId,pathLine) values(:userId,:pathLine) ") 用法

val db = YzDatabase.getInstance(this).runDao()
Thread() {
    //插入一条数据pathLine = "插入一条信息1",userId = "小小虫1",返回主键id
    val id = db?.insert(pathLine = "插入一条信息1", userId = "小小虫1")
    Log.e(tag, "id:$id")
}.start()

3.2 删

删除一条信息,返回0或1。注意:这里删除必须传ID,也就是主键,因为 @Delete 注解只根据主键识别,后面的?@Update 也是如此

@Delete 用法

val db = YzDatabase.getInstance(this).runDao()
Thread() {
    //删除ID为1的数据,返回 0:删除失败 1:删除成功
    val success = db?.delete(RunRecord().apply {
        id = 1
    })
    Log.e(tag, "success:$success")
}.start()

@Query("DELETE FROM RunRecord WHERE userId = :userId") 用法

val db = YzDatabase.getInstance(this).runDao()
Thread() {
    //删除userId = "小小虫"的数据,返回删除的条数
    val count = db?.delete( userId = "小小虫")
    Log.e(tag, "count:$count")
}.start()

@Query("DELETE FROM RunRecord") 用法

val db = YzDatabase.getInstance(this).runDao()
//删除所有数据,返回删除的条数
Thread() {
    val count = db?.deleteAll()
    Log.e(tag, "count:$count")
}.start()

3.3 改

@Query("UPDATE RunRecord SET pathLine =:info WHERE userId = :userId")用法

val db = YzDatabase.getInstance(this).runDao()
//更新 userId = "小小虫" 的一数据,修改info = ="修改一条信息"
// 返回 0:更新失败 1:更新成功
Thread() {
    val success = db?.updateRunInfo(userId = "小小虫", info = "修改一条信息")
    Log.e(tag, "success:$success")
}.start()


@Update 用法也是根据主键ID查找对应数据修改

val db = YzDatabase.getInstance(this).runDao()
//更新 id = 1 的一条数据,,返回 0:更新失败 1:更新成功
Thread() {
    val success = db?.update(RunRecord().apply {
        id = 1
        pathLine = "修改一条信息"
        userId = "小小虫1"
    })
    Log.e(tag, "success:$success")
}.start()

3.4 查

@Query("SELECT * FROM RunRecord WHERE userId LIKE :userId order by userId desc LIMIT 1")

val db = YzDatabase.getInstance(this).runDao()
Thread() {
    //根据userId获取最后一条
    val info = db?.findLastByUserId(userId = "小小虫")
    Log.e(tag, "info:$info")
}.start()

@get:Query("SELECT * FROM RunRecord")

val db = YzDatabase.getInstance(this).runDao()
//查询所有数据,返回表所有数据
Thread() {
    val info = db?.all
    info?.forEach {
        Log.e(tag, "it:$it")
    }
}.start()

四、更新数据库

当我们需要在原有的数据库里添加表或者在原有的表里添加新的字段时,需要更新数据库才能使我们新加的内容得以应用。

4.1自动迁移

注意:Room 在 2.4.0-alpha01 及更高版本中支持自动迁移。如果您的应用使用的是较低版本的 Room,则必须手动定义迁移

不建议使用这种方式,因为高版本的Room需要更新Kotlin 版本,Kotlin插件版本,Gradle版本等,而且还要升级Android Studio,我放弃了!!

关于这些具体的版本号查看这里:https://github.com/googlecodelabs/android-room-with-a-view/archive/kotlin.zip

使用

旧版本

@Database(entities = [ RunRecord::class], version = 1)
abstract class YzDatabase : RoomDatabase() {

新版本

@Database(entities = [ RunRecord::class], version = 2,
    autoMigrations = [AutoMigration (from = 1, to = 2)])
abstract class YzDatabase : RoomDatabase() {

4.2手动迁移

在RunRecord表中加一个userName字段和std字段

@ColumnInfo(name = "userName")
var userName: String? = null

@ColumnInfo(name = "std")
var std: Int? = null

步骤:

1.将version+1

@Database(entities = [ RunRecord::class], version = 2)

2.创建Migration(int startVersion,int endVersion)类,startVersion原始版本号(例如1),endVersion升级后的版本号(例如2)

提示:由于SQLite好像不支持像数据库一样多个字段添加,所以只能分开添加

val MIGRATION_1_2: Migration = object : Migration(1, 2) {
            override fun migrate(database: SupportSQLiteDatabase) {
                database.execSQL(
                    "ALTER TABLE RunRecord"
                            + " ADD COLUMN userName TEXT"
                )
                database.execSQL(
                    "ALTER TABLE RunRecord"
                            + " ADD COLUMN std INTEGER"
                )
            }
        }

3.将Mrgration添加到数据库构建中

fun getInstance(context: Context) =
    instance ?: synchronized(this) {
        instance ?: Room.databaseBuilder(
            context,
            YzDatabase::class.java, DB_NAME
        ).addMigrations(MIGRATION_1_2).build()
    }

完整代码

@Database(entities = [ RunRecord::class], version = 2)
abstract class YzDatabase : RoomDatabase() {
    abstract fun runDao(): RunDao?
    companion object {
        private const val DB_NAME = "yzWill.db"
        val MIGRATION_1_2: Migration = object : Migration(1, 2) {
            override fun migrate(database: SupportSQLiteDatabase) {
                database.execSQL(
                    "ALTER TABLE RunRecord"
                            + " ADD COLUMN userName TEXT"
                )
                database.execSQL(
                    "ALTER TABLE RunRecord"
                            + " ADD COLUMN std INTEGER"
                )
            }
        }
        @Volatile
        private var instance: YzDatabase? = null
        fun getInstance(context: Context) =
            instance ?: synchronized(this) {
                instance ?: Room.databaseBuilder(
                    context,
                    YzDatabase::class.java, DB_NAME
                ).addMigrations(MIGRATION_1_2).build()
            }
    }
}

注意:每次更新的MIGRATION_1_2MIGRATION_2_3等都要加到构建中去,不能只单单 addMigrations(MIGRATION_2_3),如果此时手机安装的数据库版本是2,那就没问题。如果是1,那么app会闪退

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-10 22:41:17  更:2022-03-10 22:43:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 19:16:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码