Android-Room使用和迁移

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. 定义数据库接口
    使用@Database注解
@Database(
    // entities可以维护多个class,代表多张数据库表
    entities = [User::class],
    version = 1,
)
abstract class UserDataBase : RoomDatabase() {
	// 返回数据库访问接口
    abstract fun userDao(): UserDao

    companion object {
        private var userDataBase: UserDataBase? = null

        fun get(context: Context): UserDataBase {
            return userDataBase ?: synchronized(this) {
                // lcj为数据库名
                Room.databaseBuilder(context, UserDataBase::class.java, "lcj")
                    .build()
                    .also {
                        userDataBase = it
                    }
            }
        }
    }

}
  1. 使用
class UserViewModel(app:Application) : AndroidViewModel(app) {

    suspend fun insert(id: Int, name: String, address: String) {
        val user = User()
        user.id = id
        user.name = name
        user.address = address
        UserDataBase.get(getApplication()).userDao().insert(user)
    }

    fun getAll(): Flow<List<User>> {
        return UserDataBase.get(getApplication()).userDao().getAll().catch {
        }.flowOn(Dispatchers.IO)
    }
}
迁移
自动迁移

使用自动迁移,需要提供schema.location配置且@DataBase中的exportSchema必须设置为TRUE(默认为TRUE)

  1. build.gradle中进行如下配置,用于生成每个版本的数据库记录,Room用来跟踪数据库的变更
    defaultConfig {
        kapt {
            arguments {
                arg("room.schemaLocation", "$projectDir/schemas")
            }
        }
    }
  1. 新增列address
@Entity(tableName = "User")
class User {

    @PrimaryKey
    var id: Int = 0

    @ColumnInfo(name = "name")
    var name: String = ""

    // 版本2新增字段
    @ColumnInfo(name = "address", defaultValue = "")
    var address: String = ""
}
  1. 在Database注解中version升级到对应版本,且autoMigrations添加from to
@Database(
    // entities可以维护多个class,代表多张数据库表
    entities = [User::class],
    // 修改版本号
    version = 2,
    // 新增自动迁移
    autoMigrations = [
        AutoMigration(from = 1, to = 2)
    ]
)
abstract class UserDataBase : RoomDatabase() {
  1. 生成的跟踪文件如下
    在这里插入图片描述

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

@Database(
    // entities可以维护多个class,代表多张数据库表
    entities = [User::class],
    version = 3,
    autoMigrations = [
        AutoMigration(from = 1, to = 2),
        AutoMigration(from = 2, to = 3, spec = UserDataBase.Migration2to3::class)
    ]
)
abstract class UserDataBase : RoomDatabase() {

    abstract fun userDao(): UserDao

    @RenameColumn(tableName = "User", fromColumnName = "address", toColumnName = "addressAt")
    class Migration2to3 : AutoMigrationSpec
手动迁移

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

companion object {
        private var userDataBase: UserDataBase? = null

        // 手动迁移
        private val migration = 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 = it
                    }
            }
        }
    }
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android RoomAndroid平台上的一个持久化库,用于处理本地数据库的操作。当在应用程序中使用Room时,可能会遇到需要进行数据迁移的情况,例如更改数据库模式或添加新的表。 在Room中进行数据迁移可以通过数据库升级来实现。下面是一些常见的步骤: 1. 在Room的Database类中,使用`@Database`注解来定义你的数据库,并指定`version`属性,表示当前数据库的版本号。 ```kotlin @Database(entities = arrayOf(User::class), version = 2) abstract class AppDatabase : RoomDatabase() { // ... } ``` 2. 创建一个新的数据库版本,并在新版本中进行必要的更改。例如,你可以添加新的实体类或更改现有实体类的结构。 ```kotlin @Database(entities = arrayOf(User::class, Order::class), version = 3) abstract class AppDatabase : RoomDatabase() { // ... } ``` 3. 创建一个用于执行数据库升级的`Migration`对象。`Migration`对象需要实现`Migration`接口,并在`migrate()`方法中定义旧版本到新版本的迁移逻辑。 ```kotlin val MIGRATION_2_3: Migration = object : Migration(2, 3) { override fun migrate(database: SupportSQLiteDatabase) { // 执行数据库迁移操作 } } ``` 4. 在创建Room的`Database`对象时,使用`.addMigrations()`方法将迁移对象添加到构建器中。 ```kotlin val db = Room.databaseBuilder( context.applicationContext, AppDatabase::class.java, "app_database" ) .addMigrations(MIGRATION_2_3) .build() ``` 这样,在应用程序升级时,Room将会自动检测到数据库版本的变化,并执行相应的迁移操作。 需要注意的是,当进行数据库迁移
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值