崩溃将沿着以下路线进行:java.lang.IllegalStateException: 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. Expected identity hash: e843da3b4913dbc08880c558d759fe82, found: d5c32de20cfd495f9eae5463c1ec7433
散列将不同(预期(第1个)是按照@Entity,找到的是按照现有数据库中的架构)
你需要做的是
将所述默认值设置为指示尚未提供移动号码的适当值,以及
添加引入新列的迁移,以及
增加版本号(这将调用迁移、执行迁移,然后处理继续到检查/打开数据库)。
如果没有迁移,则会发生崩溃,例如java.lang.IllegalStateException: A migration from 1 to 2 was required but not found. Please provide the necessary Migration path via RoomDatabase.Builder.addMigration(Migration ...) or allow for destructive migrations via one of the RoomDatabase.Builder.fallbackToDestructiveMigration* methods.
const val DATABASE_VERSION = 1 /*<<<<<<<<<< WILL CHANGE to 2 FOR V2 */
const val USER_TABLE_NAME = "user"
const val USER_NAME_COLUMN = "name"
const val USER_PASSWORD_COLUMN = "password"
@Entity(tableName = USER_TABLE_NAME)
data class User(
@PrimaryKey
@ColumnInfo(name = USER_NAME_COLUMN)
val name: String, /* Original */
@ColumnInfo(name = USER_PASSWORD_COLUMN)
val password: String /* Original */
@Dao
interface UserDAOs {
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(user: User): Long
@Query("SELECT * FROM user")
fun getAllUsers(): List<User>
}
@Database(entities = [User::class], exportSchema = false, version = DATABASE_VERSION)
abstract class TheDatabase: RoomDatabase() {
abstract fun getUserDAOs(): UserDAOs
companion object {
private var instance: TheDatabase?=null
fun getInstance(context: Context): TheDatabase {
if (instance==null) {
instance=Room.databaseBuilder(context,TheDatabase::class.java,"the_database.db")
.allowMainThreadQueries() /* for brevity of the demo */
.build()
}
return instance as TheDatabase
}
}
}
现在**加载一些V1数据的一些活动代码:-
class MainActivity : AppCompatActivity() {
lateinit var db: TheDatabase
lateinit var dao: UserDAOs
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = TheDatabase.getInstance(this)
dao = db.getUserDAOs()
dao.getAllUsers() /*<<<< force open the database in case no code runs (this when the version and schema checking and migration for V2 will take place ) */
if (DATABASE_VERSION == 1) {
dao.insert(User("Fred", "passwordFred")) /* Original */
dao.insert(User("Mary", "passwordMary")) /* Original */
}
/* commented out for V1 as mobile not a field in the User */
/*
if (DATABASE_VERSION == 2) {
dao.insert(User("Jane","passwordJane","1234567890"))
dao.insert(User("John","passwordJohn","0987654321"))
dao.insert(User("Pat","passwordPat"))
}
*/
}
}
当运行进行全新安装(即旧用户)时,通过应用程序检查:-
room_master_table是存储架构散列的位置,将是找到的
如所期望的,这两行存在并且具有期望值。
下一步**代码更改。
数据库代码变为:- 数据库版本增加:-
const val DATABASE_VERSION = 2 /*<<<<<<<<<< WILL CHANGE to 2 FOR V2 */
添加了2个新的常量值:-
const val USER_MOBILE_COLUMN = "mobile" /*<<<<<<<<<< ADDED for V2 */
const val USER_MOBILE_DEFAULT_VALUE = "xxxxxxxxxx" /*<<<<<<<<<< ADDED for V2 */
用户类变为:-
@Entity(tableName = USER_TABLE_NAME)
data class User(
@PrimaryKey
@ColumnInfo(name = USER_NAME_COLUMN)
val name: String, /* Original */
@ColumnInfo(name = USER_PASSWORD_COLUMN)
val password: String /* Original */ ,/*<<<<<<<<< ADDED comma FOR V2 */
/*<<<<<<<<<< SCHEMA CHANGES FOR V2 (see comma above) >>>>>>>>>>*/
@ColumnInfo(name = USER_MOBILE_COLUMN, defaultValue = USER_MOBILE_DEFAULT_VALUE) /*<<<<<<<<<< ADDED FOR V2 */
val mobile: String = "not provided" /*<<<<<<<<<< ADDED for V2 (default value allows mobile to not be given for V1 code in Main Activity)*/
)
@Database注解类TheDatabase添加了迁移:-
@Database(entities = [User::class], exportSchema = false, version = DATABASE_VERSION)
abstract class TheDatabase: RoomDatabase() {
abstract fun getUserDAOs(): UserDAOs
companion object {
private var instance: TheDatabase?=null
fun getInstance(context: Context): TheDatabase {
if (instance==null) {
instance=Room.databaseBuilder(context,TheDatabase::class.java,"the_database.db")
.allowMainThreadQueries() /* for brevity of the demo */
.addMigrations(MIGRATE_1_to_2)
.build()
}
return instance as TheDatabase
}
val MIGRATE_1_to_2: Migration = object: Migration(1,2){
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("ALTER TABLE $USER_TABLE_NAME ADD COLUMN $USER_MOBILE_COLUMN TEXT NOT NULL DEFAULT '$USER_MOBILE_DEFAULT_VALUE'")
/* So as to show Migration add a row when migrating (would not be done normally) */
val cv = ContentValues()
cv.put(USER_NAME_COLUMN,"Alice")
cv.put(USER_PASSWORD_COLUMN,"passwordAlice")
cv.put(USER_MOBILE_COLUMN,"1111111111")
db.insert(USER_TABLE_NAME,OnConflictStrategy.IGNORE,cv)
}
}
}
}
注解掉的活动代码在V2中未注解:-
class MainActivity : AppCompatActivity() {
lateinit var db: TheDatabase
lateinit var dao: UserDAOs
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = TheDatabase.getInstance(this)
dao = db.getUserDAOs()
dao.getAllUsers() /*<<<< force open the database in case no code runs */
if (DATABASE_VERSION == 1) {
dao.insert(User("Fred", "passwordFred")) /* Original */
dao.insert(User("Mary", "passwordMary")) /* Original */
}
/* commented out for V1 as mobile not a field in the User */
if (DATABASE_VERSION == 2) {
dao.insert(User("Jane","passwordJane","1234567890"))
dao.insert(User("John","passwordJohn","0987654321"))
dao.insert(User("Pat","passwordPat"))
}
}
}
1条答案
按热度按时间xytpbqjk1#
除非是不同的应用程序,否则更新将通过PlayStore向老用户推出。
你必须更新老用户,否则应用程序会崩溃。不过,你可以保留他们的数据,但你必须迎合新的专栏。
由于模式已更改(新列),并且如果没有迁移,则老用户将遇到崩溃,因为Room会根据
@Entity
注解类(预期)检查模式是否与数据库(发现)一致。java.lang.IllegalStateException: 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. Expected identity hash: e843da3b4913dbc08880c558d759fe82, found: d5c32de20cfd495f9eae5463c1ec7433
@Entity
,找到的是按照现有数据库中的架构)你需要做的是
java.lang.IllegalStateException: A migration from 1 to 2 was required but not found. Please provide the necessary Migration path via RoomDatabase.Builder.addMigration(Migration ...) or allow for destructive migrations via one of the RoomDatabase.Builder.fallbackToDestructiveMigration* methods.
以下是一个演示,它将首先使用V1的数据库创建应用程序,但不使用"移动"字段/列,然后在数据库升级到V2时迁移现有数据库。现有用户将具有一个指示无移动的值。
当运行进行全新安装(即旧用户)时,通过应用程序检查:-
数据库代码变为:-
数据库版本增加:-
添加了2个新的常量值:-
用户类变为:-
@Database注解类TheDatabase添加了迁移:-
注解掉的活动代码在V2中未注解:-
当应用程序运行时,应用程序检查现在显示:-
可以看出:
剩下的概念验证是当新用户安装应用程序时,即全新安装。在此场景中,对于演示,将仅插入三个V2用户(Jane、John和Pat):