热门标签 | 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标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ... [详细]
  • CentOS 6.5安装VMware Tools及共享文件夹显示问题解决方法
    本文介绍了在CentOS 6.5上安装VMware Tools及解决共享文件夹显示问题的方法。包括清空CD/DVD使用的ISO镜像文件、创建挂载目录、改变光驱设备的读写权限等步骤。最后给出了拷贝解压VMware Tools的操作。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • Java学习笔记之使用反射+泛型构建通用DAO
    本文介绍了使用反射和泛型构建通用DAO的方法,通过减少代码冗余度来提高开发效率。通过示例说明了如何使用反射和泛型来实现对不同表的相同操作,从而避免重复编写相似的代码。该方法可以在Java学习中起到较大的帮助作用。 ... [详细]
  • 本文讨论了如何使用Web.Config进行自定义配置节的配置转换。作者提到,他将msbuild设置为详细模式,但转换却忽略了带有替换转换的自定义部分的存在。 ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
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社区 版权所有