我正在嘗試將我的 Room db 遷移到下一個版本,但我不斷收到相同的錯誤:
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.
我的資料庫版本之間的唯一區別是我添加了一個新列。遷移是這樣處理的:
@Database(
version = 2,
entities = [Note::class],
exportSchema = true)
abstract class AppDatabase : RoomDatabase() {
abstract fun noteDao(): NoteDAO
companion object {
fun build(context: Context) = Room.databaseBuilder(context, AppDatabase::class.java, "NotesDatabase")
.addMigrations(MIGRATION_1_2).build()
}
}
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE Notes ADD COLUMN image STRING")
}
}
我不確定我是否正確實施了這一點。該錯誤告訴我我必須以某種方式呼叫 .build()。我在使用資料庫的活動中嘗試過,但錯誤是一樣的,所以我洗掉了那個呼叫。
我怎樣才能解決這個問題?
uj5u.com熱心網友回復:
看來您沒有呼叫 build 函式,并且可能有另一種構建資料庫的方法(呼叫 databaseBuilder)。
例如,在活動/片段中,您有以下內容:-
class MainActivity : AppCompatActivity() {
lateinit var db: AppDatabase
lateinit var dao: NoteDAO
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = Room.databaseBuilder(this,AppDatabase::class.java,"NotesDatabase")
.allowMainThreadQueries()
.build()
dao = db.noteDao()
dao.getAllNotes()
}
}
這在更改 Note 物體并將版本增加到 2 之后會產生結果,例如:-
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.
相反,您需要呼叫 AppDatabase 的構建函式
所以上面會變成: -
class MainActivity : AppCompatActivity() {
lateinit var db: AppDatabase
lateinit var dao: NoteDAO
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = AppDatabase.build(this) //<<<<<<<<<< CHANGED
dao = db.noteDao()
dao.getAllNotes() // Forces database access/open
}
}
但是,您將收到 Expected/Found 問題,例如:-
2022-03-21 09:15:20.385 14533-14533/a.a.so71549033kotlinroommigration E/AndroidRuntime: FATAL EXCEPTION: main
Process: a.a.so71549033kotlinroommigration, PID: 14533
java.lang.RuntimeException: Unable to start activity ComponentInfo{a.a.so71549033kotlinroommigration/a.a.so71549033kotlinroommigration.MainActivity}: java.lang.IllegalStateException: Migration didn't properly handle: notes(a.a.so71549033kotlinroommigration.Note).
Expected:
TableInfo{name='notes', columns={noteText=Column{name='noteText', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, image=Column{name='image', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, noteId=Column{name='noteId', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}}, foreignKeys=[], indices=[]}
Found:
TableInfo{name='notes', columns={noteText=Column{name='noteText', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, image=Column{name='image', type='STRING', affinity='1', notNull=false, primaryKeyPosition=0, defaultValue='null'}, noteId=Column{name='noteId', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}}, foreignKeys=[], indices=[]}
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
This is because STRING, as far as room is concerned, is not a valid column type.
In the above you can see/extract that room expects :-
image=Column{name='image', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}
BUT Room found :-
image=Column{name='image', type='STRING', affinity='1', notNull=false, primaryKeyPosition=0, defaultValue='null'}
Room only accepts column types of INTEGER, REAL, TEXT and BLOB (even though SQLite is far more flexible with column types).
The type depends upon the type of the variable, furthermore Room is also very specific about other parts of the definition, such as whether or not NOT NULL should be part and whether or not DEFAULT should be part of the definition or not.
However, Room allows you to ascertain exactly what the column definition should be. If you make the changes to the entity(ies) and compile the project then java code is generated by Room, this includes the SQL used to create the table(s) and within this SQL are the expected column definitions.
From the Android Studio Project View you will see Java (generated)
, within the classes/files under this will be some classes one of which will be AppDatabase_Impl. Within this class there will be a method createAlltables. Within this method is the SQL for all the tables.
e.g. :-
- Note the image column, in this case, was coded as
var image: String
- String equates to TEXT and also NOT NULL. String? would not have NOT NULL
However, if ALTERing a table and adding a column with NOT NULL then SQLite requires that a DEFAULT is provided that is not null, as per:- f a NOT NULL constraint is specified, then the column must have a default value other than NULL. https://www.sqlite.org/lang_altertable.html
So in the case above then for the found to be what room expects then the ALTER SQL should be :-
ALTER TABLE Notes ADD COLUMN image TEXT NOT NULL DEFAULT 'unknown'
'unknown'
could be whatever suits
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/446370.html
上一篇:合并索引上的兩個DataFrame,但是如果一個DF缺少索引,我希望它在其中一個DF缺少該索引時創建Null(Nan)值