Jetpack Room是Android官方提供的一个持久化库,旨在简化Android应用程序中的数据库操作。它提供了一个抽象层,使开发人员能够以面向对象的方式处理数据库操作,而无需编写复杂的SQL查询语句。通过使用Jetpack Room,开发人员可以更快速、更高效地构建稳健的数据库驱动应用程序。
Room 最新版本为2.5.2
Android Studio版本为 Android Studio Flamingo | 2022.2.1 Patch 2
Android使用Jetpack Room管理数据库 – 第一弹
Android使用Jetpack Room管理数据库 – 第二弹
开篇
上一篇文章我们介绍了Room的入门使用和Entity
的高阶用法,基本包含了日常开发所需的大部分知识,但是还缺少了一个重要的功能,那就是数据库的升级,在日常版本迭代中,升级数据库是避免不了的,下面我们进入Room升级功能中瞅一瞅。
新增字段
这里还是接着上一篇的UserEntity
来继续介绍Room增加字段之后该如何处理,当我们为UserEntity
添加age
字段之后,此时如果不对Room做任何处理,那么在运行的过程中会产生Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number
错误提示,它告诉我们在Room中要对新增的age
字段做升级处理并且修改数据库的版本号。
下面我们先进行数据库版本号的升级
@Database(entities = [UserEntity::class], version = 2, exportSchema = false)
abstract class RoomDb : RoomDatabase() {
abstract fun getUserDao(): UserDao
}
在RoomDb
的类注解中,将version
字段+1,此时版本号变为2,仅修改这里还是不够,虽然数据库的版本号升级了,但是Room不知道age
这个字段该如何处理,接下来我们通过Migration
来进行字段的添加。
val addAge = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE user_entity add column age INTEGER NOT NULL DEFAULT 0")
}
}
Migration
专门为数据库升级提供服务,我们在migrate()
方法中通过SQL语句新增了age
字段,此SQL还是比较简单的,就是往user_entity
数据表中添加age
字段,标明是一个Int
类型并且不可为空,默认值为0,以此类推String
可设置为空字符串。migrate(startVersion, endVersion)
前两个参数就是升级前的版本号和升级后的版本号,版本号千万不能写错,不然升级就会报错了。
处理完SQL之后,最后只需要配置给Room.databaseBuilder()
即可。
single {
Room.databaseBuilder(androidContext(), RoomDb::class.java, "room_db")
.addMigrations(addAge)
.build()
}
到这为止我们就完成了数据表新增字段的操作了,下面看下新增一条数据的效果
通过App Inspection就可以看到新增的age
字段已经在表中了。
新增表
上面我们了解了如何向数据表中新增字段的操作,接下来我们看看如何新增一张全新的数据表操作。假设我们在需求中需要保存房间的信息,房间信息包含id
和name
等字段,这时候我们就需要按照下面操作来进行新增表:
- 定义房间数据类,并加上
@Entity
注解 - 创建房间的
Dao
接口 - 在
RoomDatabase
增加entity
数据,并且修改版本号,增加获取HomeDao
的抽象方法 - 最后在
Room.databaseBuilder()
新增表结构
定义Home数据类
@Entity(tableName = "home_entity")
data class Home(
@PrimaryKey
val id: Int,
val name: String
)
定义Home
表结构字段、表名和主键
创建HomeDao
接口
@Dao
interface HomeDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertHome(home: Home)
}
创建HomeDao
接口,别忘记@Dao
注解哦,这里就定义一个插入方法来演示,其余修改、删除等操作这里就不再多说,第一篇已经介绍过。
修改RoomDatabase
@Database(entities = [UserEntity::class, Home::class], version = 3, exportSchema = false)
abstract class RoomDb : RoomDatabase() {
abstract fun getUserDao(): UserDao
abstract fun getHomeDao(): HomeDao
}
这里修改点有三处,首先要将Home
添加Daoentities
数组中,然后将version
字段+1,最后新增getHomeDao()
抽象方法,Room会字段为我们实现此方法的具体逻辑。
新增Home表
我们需要先定义migrate
来告诉Room新增的home_entity
表结构,然后通过addMigrations
操作来让Room执行数据表的新增。
val addHomeEntity = object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE IF NOT EXISTS `home_entity` (`id` INTEGER NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`id`))")
}
}
Room.databaseBuilder(androidContext(), RoomDb::class.java, "room_db")
.addMigrations(addAge)
.addMigrations(addHomeEntity)
.build()
在database.execSQL()
的写法中有一个小技巧,对于字段少的表来说我们可以一个字段一个字段的写类型,如果新增的表结构非常复杂,此时我们可以先不着急写SQL语句,我们先reBuild
下工程,然后在build/generated/source/kapt/debug/包名
下找到RoomDb_Impl.java
图片标红的地方就是Room自动生成的SQL语句,我们只需要Copy一下,这样就帮助我们解决繁琐的语句了。
到这为止新增表的操作就全部完成了,接下来我们插入一条数据看看home_entity
表数据。
依旧是通过App Inspection观察数据库,可以看到我们新增的home_entity
表已经完成了,并且里面还有一条插入的数据。
结尾
数据库的升级就介绍完啦,日常开发中新增字段和新增表的操作都已经在上面阐述了,如果还有其它的问题,欢迎评论区一起讨论???