房间数据库在重新启动应用程序时丢失数据
Posted
技术标签:
【中文标题】房间数据库在重新启动应用程序时丢失数据【英文标题】:Room databse loses data on restart application 【发布时间】:2020-11-05 23:24:08 【问题描述】:根据来自Room.databaseBuilder()
的文档室实例应该保存数据是持久的。但还是会迷路。我的项目必须数据库
-
第一个数据库
@Database(entities = [FoodModel::class],版本 = 4,exportSchema = false) 抽象类 FoodDatabase : RoomDatabase()
abstract val foodDatabaseDao: FoodDatabaseDao
companion object
@Volatile
private var INSTANCE: FoodDatabase? = null
fun getInstance(context: Context): FoodDatabase
synchronized(this)
var instance = INSTANCE
if (instance == null)
instance = Room.databaseBuilder(
context.applicationContext,
FoodDatabase::class.java,
Constants.OVERVIEW_FOOD_DATABASE
)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
return instance
第二个数据库
@Database(entities = [MyFoodModel::class], version = 3, exportSchema = false)
抽象类 MyFoodDatabase : RoomDatabase() abstract val myFoodDatabaseDao: MyFoodDatabaseDao
companion object
@Volatile
private var INSTANCE: MyFoodDatabase? = null
fun getInstance(context: Context): MyFoodDatabase
synchronized(this)
var instance = INSTANCE
if (instance == null)
instance = Room.databaseBuilder(
context.applicationContext,
MyFoodDatabase::class.java,
Constants.OVERVIEW_FOOD_DATABASE
)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
return instance
第一个数据库的道
@Dao
interface MyFoodDatabaseDao
@Insert
fun insert(food: MyFoodModel)
@Query("SELECT * FROM MyFoodItems ORDER BY name DESC")
fun getAllFood(): LiveData<List<MyFoodModel>>
@Delete
fun deleteFood(foodModel: MyFoodModel)
第二数据库之道
@Dao
interface MyFoodDatabaseDao
@Insert
fun insert(food: MyFoodModel)
@Query("SELECT * FROM MyFoodItems ORDER BY name DESC")
fun getAllFood(): LiveData<List<MyFoodModel>>
@Delete
fun deleteFood(foodModel: MyFoodModel)
【问题讨论】:
您是否丢失了两个数据库上的数据?您可能没有插入它们。在您插入的位置显示您的 DAO 和代码。 为两个数据库添加了 Dao,当应用程序只有一个数据库时,它工作得很好,但是在添加第二个数据库后,应用程序在重新启动时会丢失所有数据。 【参考方案1】:一个 android 应用程序可以有多个数据库。
正如我所见,您为两个数据库 [MyFoodDatabase, FoodDatabase] 提供了相同的名称 [Constants.OVERVIEW_FOOD_DATABASE]。因此所有值都将写入一个名为 Constants.OVERVIEW_FOOD_DATABASE 的数据库中。
请提供两个数据库不同的名称,然后重试。
已编辑
正如您所说,您正在使用相同数据库的两个不同实例,并且对于每个数据库实例,您正在更改数据库版本,但您没有将数据库迁移到该版本。相反,您使用的 fallbackToDestructiveMigration() 不会使数据库崩溃,但会在找到任何现有版本时清除数据。
请尝试以下步骤:
-
从两个数据库实例中删除 fallbackToDestructiveMigration()。
在第二个实例中添加 .addMigrations(MIGRATION_1_2) 同时创建
实例
val MIGRATION_1_2 = object : Migration(1, 2)
override fun migrate(database: SupportSQLiteDatabase)
// do nothing because you are not altering any table
-
在第一个实例中,在创建实例时添加 .addMigrations(MIGRATION_2_1)
val MIGRATION_2_1 = object : Migration(2, 1)
override fun migrate(database: SupportSQLiteDatabase)
// do nothing because you are not altering any table
它将迁移您相同的数据库。就我而言,它正在工作。我希望它也适用于你的情况。 :)
但最好使用单个数据库实例并在注释中包含与数据库关联的实体列表。 因为房间数据库实例很昂贵。
https://developer.android.com/training/data-storage/room
注意:如果您的应用在单个进程中运行,则在实例化 AppDatabase 对象时应遵循单例设计模式。每个 RoomDatabase 实例都相当昂贵,您很少需要在单个进程中访问多个实例。
如果您的应用在多个进程中运行,请在您的数据库构建器调用中包含 enableMultiInstanceInvalidation()。这样,当您在每个进程中都有一个 AppDatabase 实例时,您可以使一个进程中的共享数据库文件失效,并且这种失效会自动传播到其他进程中的 AppDatabase 实例。
【讨论】:
应用程序应将所有数据保存在单个数据库中。我正在创建单个数据库的两个不同实例,但表名不同,因此值不会被覆盖。 哦,我误解了你的问题,我以为你想创建 2 个不同的数据库。无论如何我已经编辑了我的答案,请检查 数据库迁移不起作用(我认为因为迁移仅适用于更新具有新更改的数据库),现在我使用两个数据库,两个数据库上都有一个表。以上是关于房间数据库在重新启动应用程序时丢失数据的主要内容,如果未能解决你的问题,请参考以下文章
Heroku:每次测功机重新启动时都会丢失 Django 数据库文件
cmd启动数据库时,出现 (无法启动此程序,因为计算机中丢失VCRUNTIME140_1.dll 尝试重新安装此程序以解决此问题 )解决方法。