热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

AndroidRoom使用和迁移

RoomSQL基础上的一个抽象层使用引入依赖defroom_version2.4.3implementationandroidx.room:room-runtime



Room


  1. SQL基础上的一个抽象层

使用


  1. 引入依赖

def room_version = "2.4.3"
implementation "androidx.room:room-runtime:$room_version"
// To use Kotlin annotation processing tool (kapt)
kapt "androidx.room:room-compiler:$room_version"
implementation("androidx.room:room-ktx:$room_version")

  1. 定义数据库表
    使用@Entity注解

@Entity(tableName = "User")
class User {
@PrimaryKey
var id: Int = 0
@ColumnInfo(name = "name")
var name: String = ""
@ColumnInfo(name = "address", defaultValue = "")
var address: String = ""
}

  1. 定义数据表操作接口
    使用@Dao注解

@Dao
interface UserDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(user: User)
@Query("select * from user")
fun getAll() : Flow<List<User>>
}

  1. 定义数据库接口
    使用&#64;Database注解

&#64;Database(
// entities可以维护多个class,代表多张数据库表
entities &#61; [User::class],
version &#61; 1,
)
abstract class UserDataBase : RoomDatabase() {
// 返回数据库访问接口
abstract fun userDao(): UserDao
companion object {
private var userDataBase: UserDataBase? &#61; null
fun get(context: Context): UserDataBase {
return userDataBase ?: synchronized(this) {
// lcj为数据库名
Room.databaseBuilder(context, UserDataBase::class.java, "lcj")
.build()
.also {
userDataBase &#61; it
}
}
}
}
}

  1. 使用

class UserViewModel(app:Application) : AndroidViewModel(app) {
suspend fun insert(id: Int, name: String, address: String) {
val user &#61; User()
user.id &#61; id
user.name &#61; name
user.address &#61; address
UserDataBase.get(getApplication()).userDao().insert(user)
}
fun getAll(): Flow<List<User>> {
return UserDataBase.get(getApplication()).userDao().getAll().catch {
}.flowOn(Dispatchers.IO)
}
}

迁移


自动迁移

使用自动迁移&#xff0c;需要提供schema.location配置且&#64;DataBase中的exportSchema必须设置为TRUE&#xff08;默认为TRUE&#xff09;

  1. build.gradle中进行如下配置&#xff0c;用于生成每个版本的数据库记录&#xff0c;Room用来跟踪数据库的变更

defaultConfig {
kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas")
}
}
}

  1. 新增列address

&#64;Entity(tableName &#61; "User")
class User {
&#64;PrimaryKey
var id: Int &#61; 0
&#64;ColumnInfo(name &#61; "name")
var name: String &#61; ""
// 版本2新增字段
&#64;ColumnInfo(name &#61; "address", defaultValue &#61; "")
var address: String &#61; ""
}

  1. 在Database注解中version升级到对应版本&#xff0c;且autoMigrations添加from to

&#64;Database(
// entities可以维护多个class,代表多张数据库表
entities &#61; [User::class],
// 修改版本号
version &#61; 2,
// 新增自动迁移
autoMigrations &#61; [
AutoMigration(from &#61; 1, to &#61; 2)
]
)
abstract class UserDataBase : RoomDatabase() {

  1. 生成的跟踪文件如下
    在这里插入图片描述

注意&#xff1a;上面步骤&#xff0c;完成数据库中添加一列的升级。每当数据库版本再次改变时&#xff0c;您只需更新 autoMigrations 列表&#xff0c;添加一个新的AutoMigration即可。上述数据库表中新增了address列&#xff0c;对于自动迁移&#xff0c;Room自动会检测中这种变更&#xff0c;不需要开发者做其他操作。
但是&#xff0c;有些自动迁移操作&#xff0c;Room无法检测出变化&#xff0c;需要开发者添加额外的spec,如&#xff0c;修改表名、列名、删除表、删除列&#xff0c;需要添加如下代码
&#64;DeleteTable(tableName)
&#64;RenameTable(fromTableName, toTableName)
&#64;DeleteColumn(tableName, columnName)
&#64;RenameColumn(tableName, fromColumnName, toColumnName)
下面代码是从版本2升级到版本3&#xff0c;用于修改列名&#xff0c;此处在AutoMigration中添加了spec

&#64;Database(
// entities可以维护多个class,代表多张数据库表
entities &#61; [User::class],
version &#61; 3,
autoMigrations &#61; [
AutoMigration(from &#61; 1, to &#61; 2),
AutoMigration(from &#61; 2, to &#61; 3, spec &#61; UserDataBase.Migration2to3::class)
]
)
abstract class UserDataBase : RoomDatabase() {
abstract fun userDao(): UserDao
&#64;RenameColumn(tableName &#61; "User", fromColumnName &#61; "address", toColumnName &#61; "addressAt")
class Migration2to3 : AutoMigrationSpec

手动迁移

针对手动&#xff0c;Room 提供了 Migration 类。每当您要更改复杂的数据库时&#xff0c;您就得使用这个类。如&#xff1a;将数据库中的一个表拆分成两个不同的表&#xff0c;Room 无法检测到拆分的执行过程&#xff0c;也不能自动检测到需要移动的数据。因此这个时候&#xff0c;您需要实现一个 Migration 类&#xff0c;并通过 addMigrations() 的方法将其添加至 databaseBuilder() 中。

companion object {
private var userDataBase: UserDataBase? &#61; null
// 手动迁移
private val migration &#61; object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
// 在这里进行手动迁移操作
}
}
fun get(context: Context): UserDataBase {
return userDataBase ?: synchronized(this) {
// lcj为数据库名
Room.databaseBuilder(context, UserDataBase::class.java, "lcj")
// 使用addMigrations添加自动迁移
.addMigrations(migration).build()
.also {
userDataBase &#61; it
}
}
}
}






推荐阅读
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 在Kubernetes上部署JupyterHub的步骤和实验依赖
    本文介绍了在Kubernetes上部署JupyterHub的步骤和实验所需的依赖,包括安装Docker和K8s,使用kubeadm进行安装,以及更新下载的镜像等。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 本文介绍了在iOS开发中使用UITextField实现字符限制的方法,包括利用代理方法和使用BNTextField-Limit库的实现策略。通过这些方法,开发者可以方便地限制UITextField的字符个数和输入规则。 ... [详细]
author-avatar
he恋613_394
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有