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")
@Entity(tableName = "User")
class User {
@PrimaryKey
var id: Int = 0
@ColumnInfo(name = "name")
var name: String = ""
@ColumnInfo(name = "address", defaultValue = "")
var address: String = ""
}
@Dao
interface UserDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(user: User)
@Query("select * from user")
fun getAll() : Flow<List<User>>
}
@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
}
}
}
}
}
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)
defaultConfig {
kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas")
}
}
}
@Entity(tableName = "User")
class User {
@PrimaryKey
var id: Int = 0
@ColumnInfo(name = "name")
var name: String = ""
// 版本2新增字段
@ColumnInfo(name = "address", defaultValue = "")
var address: String = ""
}
@Database(
// entities可以维护多个class,代表多张数据库表
entities = [User::class],
// 修改版本号
version = 2,
// 新增自动迁移
autoMigrations = [
AutoMigration(from = 1, to = 2)
]
)
abstract class UserDataBase : RoomDatabase() {
注意:上面步骤,完成数据库中添加一列的升级。每当数据库版本再次改变时,您只需更新 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
}
}
}
}