【问题标题】:Adding second Room database to my app causes exception: " Caused by: java.lang.IllegalStateException: Room cannot verify the data integrity"将第二个 Room 数据库添加到我的应用程序会导致异常:“原因:java.lang.IllegalStateException:Room 无法验证数据完整性”
【发布时间】:2022-01-23 10:09:21
【问题描述】:

我正在创建一个像素艺术编辑器应用程序,并且我已经有一个 Room 数据库来存储用户的创作和另一个我想要添加的 Room 数据库,它将存储一些用户想要添加到应用程序中的自定义调色板。

为此,我添加了以下数据库:

@Database(entities = [ColorPalette::class], version = 3)
abstract class ColorPalettesDatabase: RoomDatabase() {
    abstract fun colorPalettesDao(): ColorPalettesDao

    companion object {
        private var instance: ColorPalettesDatabase? = null
        fun getDatabase(context: Context): ColorPalettesDatabase {
            if (instance == null) {
                synchronized(ColorPalettesDatabase::class) {
                    if (instance == null) instance = Room.databaseBuilder(context.applicationContext, ColorPalettesDatabase::class.java, AppData.colorPalettesDBFileName).allowMainThreadQueries().build()
                }
            }
            return instance!!
        }
    }
}

还有 DAO:

@Dao
interface ColorPalettesDao {
    @Insert
    suspend fun insertColorPalette(colorPalette: ColorPalette)

    @Query("SELECT * FROM ColorPalette ")
    fun getAllColorPalettes(): LiveData<List<ColorPalette>>

    @Query("DELETE FROM ColorPalette WHERE objId=:colorPaletteId")
    fun deleteColorPalette(colorPaletteId: Int)
}

我在AppData 中添加了一个变量,并在MainActivity 的onCreate 方法中对其进行了初始化:

class AppData {
    companion object {
        var pixelArtDBFileName = "pixel_art_db"
        lateinit var pixelArtDB: PixelArtDatabase

        var colorPalettesDBFileName = "color_palettes_db"
        lateinit var colorPalettesDB: ColorPalettesDatabase
    }
}
        AppData.colorPalettesDB = ColorPalettesDatabase.getDatabase(this)

最后,我使用ColorPalettesFragment.kt 文件中的数据库从数据库中获取ColorPalette 数据:

class ColorPalettesFragment(private val lifecycleOwner: LifecycleOwner) : Fragment(), ColorPalettesListener {
    private var _binding: FragmentColorPalettesBinding? = null

    private val binding get() = _binding!!

    private lateinit var caller: ColorPalettesFragmentListener

    private fun setUpRecyclerView() {
        binding.apply {
            fragmentColorPalettesRecyclerView.layoutManager = LinearLayoutManager(this@ColorPalettesFragment.activity).apply {
                orientation = LinearLayoutManager.HORIZONTAL
            }
            AppData.colorPalettesDB.colorPalettesDao().getAllColorPalettes().observe(lifecycleOwner) {
                fragmentColorPalettesRecyclerView.adapter = ColorPalettesAdapter(it, this@ColorPalettesFragment)
            }
        }
    }

    companion object {
        fun newInstance(lifecycleOwner: LifecycleOwner) = ColorPalettesFragment(lifecycleOwner)
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        if (context is ColorPalettesFragmentListener) caller = context
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        _binding = FragmentColorPalettesBinding.inflate(inflater, container, false)

        setUpRecyclerView()

        return binding.root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    override fun onColorPaletteTapped(selectedColorPalette: ColorPalette) {
        caller.onColorPaletteTapped(selectedColorPalette)
    }
}

到目前为止,我在数据库为空时对其进行测试,我期望的是,每当用户点击以下按钮时,他们会看到一个空白 RecyclerView:

不幸的是,当我运行应用程序并尝试导航到 Canvas 时,我什至无法进入屏幕,但出现以下异常:

2021-12-22 08:55:57.251 24474-24554/com.realtomjoney.pyxlmoose E/AndroidRuntime: FATAL EXCEPTION: arch_disk_io_1
    Process: com.realtomjoney.pyxlmoose, PID: 24474
    java.lang.RuntimeException: Exception while computing database live data.
        at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:92)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:920)
     Caused by: 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.
        at androidx.room.RoomOpenHelper.checkIdentity(RoomOpenHelper.java:154)
        at androidx.room.RoomOpenHelper.onOpen(RoomOpenHelper.java:135)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onOpen(FrameworkSQLiteOpenHelper.java:201)
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:427)
        at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:316)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:151)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:112)
        at androidx.room.RoomDatabase.inTransaction(RoomDatabase.java:706)
        at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.java:483)
        at androidx.room.RoomDatabase.query(RoomDatabase.java:526)
        at androidx.room.util.DBUtil.query(DBUtil.java:86)
        at com.realtomjoney.pyxlmoose.dao.ColorPalettesDao_Impl$4.call(ColorPalettesDao_Impl.java:108)
        at com.realtomjoney.pyxlmoose.dao.ColorPalettesDao_Impl$4.call(ColorPalettesDao_Impl.java:105)
        at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:90)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:920) 

我已尝试查看其他解决方案以进行修复,但似乎没有任何帮助。

这来自ColorPalettesDatabase,因为当我在代码中删除它的所有用法时,异常消失了。

如有任何帮助,我将不胜感激,以便我可以将调色板功能添加到我的应用程序中。

不幸的是,更新版本没有帮助,因此无法卸载应用程序。

有趣的评论:我想在未来奖励这个,但不幸的是我不能因为我在一个没有回复的问题上浪费了 150 声望,哈哈

【问题讨论】:

    标签: android kotlin android-room


    【解决方案1】:

    听起来您有一个现有版本的数据库并更改了架构(即更改了ColorPalette 类)。

    Room 已检测到此更改,因此建议您增加版本号。但是,您似乎没有任何迁移,因此更改版本号会失败。

    如果你没有数据(听起来像根据 到目前为止我在数据库为空时测试它,我期望的是每当用户点击他们的以下按钮时将看到一个空白的 RecyclerView:)。编码.fallbackToDestructiveMigration 可能会解决这个问题,因为在没有迁移的情况下,它会删除表然后创建表。

    但是,上面没有回答 因此没有卸载应用程序。。所以猜测一下,您可能会遇到一个持续存在的问题。

    我建议先添加.fallbackToDestructiveMigration 然后重新运行,如果失败,则编辑您的问题以包含失败。

    接下来,假设失败,尝试卸载并重新运行,然后,假设失败,在该场景下编辑您的问题。


    问题演示

    ColorPalette 类 - 有关运行,请参阅 cmets

    @Entity
    data class ColorPalette(
        /* original V3 code */
        @PrimaryKey
        @ColumnInfo(name = "objId")
        val objId: Long? = null,
        val description: String,
        val color: Long
        /* additional code */
        ,
        val extra: String
    )
    

    ColorPaletteDao(同条无 LiveData)

    @Dao
    interface ColorPalettesDao {
        @Insert
        fun insertColorPalette(colorPalette: ColorPalette)
    
        @Query("SELECT * FROM ColorPalette ")
        fun getAllColorPalettes(): /*LiveData<*/List<ColorPalette>/*>*/ /* for testing without LiveData */
    
        @Query("DELETE FROM ColorPalette WHERE objId=:colorPaletteId")
        fun deleteColorPalette(colorPaletteId: Int)
    }
    

    ColorPalleteDatabase(相同但见后文)

    MainActivity演示

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            val db = ColorPalettesDatabase.getDatabase(this)
            val dao = db.colorPalettesDao()
            dao.getAllColorPalettes()
        }
    }
    

    Run 1 - 只有 ColorPalette 的原始代码,即没有 extra 列。

    • 运行创建好的数据库(根据 AppInspection):-

    运行 2 - 引入 extra 列,不做任何其他操作,然后运行

    • 哎呀!!!! java.lang.RuntimeException: Unable to start activity ComponentInfo{a.a.so70444736kotlinroomincreaseversion/a.a.so70444736kotlinroomincreaseversion.MainActivity}: 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.

    运行 3 - 将版本号从 3 增加到 4 并运行

    • 哎呀!!!! java.lang.RuntimeException: Unable to start activity ComponentInfo{a.a.so70444736kotlinroomincreaseversion/a.a.so70444736kotlinroomincreaseversion.MainActivity}: java.lang.IllegalStateException: A migration from 3 to 4 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. at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)

    运行 4 将 .fallbackToDestructiveMigration() 添加到 ColorPaletteDatabase 并运行

    • 运行正常,数据库:-

    将所有内容重置回初始状态(包括卸载应用程序)并运行Run 1和Run 2

    • 与预期的 Run 2 相同的问题。

    卸载应用程序但没有任何更改(所以额外的列和版本 3)

    • 运行良好,数据库有 extra 列

    因此

    为什么建议还有其他问题,因为两者都建议初始修复:-

    1. 与.fallbackToDestructiveMigration一起增加版本,并且
    2. 卸载应用并重新运行

    两者都可以纠正报告的问题。

    【讨论】:

    • 太棒了,我只能说。
    猜你喜欢
    • 2017-10-27
    • 2019-04-04
    • 2017-11-16
    • 2020-09-13
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    相关资源
    最近更新 更多