【发布时间】:2020-09-18 13:54:40
【问题描述】:
我正在尝试让我的应用程序备份和恢复其数据库文件(例如 mydatabase.db)。备份运行良好 - 它导出单个 .db 文件。它不会导出 -shm / -wal 文件,因为我运行“pragma wal_checkpoint(full)”来刷新对主文件的任何更新。 恢复似乎运行良好,但之后当我的应用查询新复制的数据时出现此错误(但应用不会崩溃)。
E/ROOM: Invalidation tracker is initialized twice :/.
E/SQLiteLog: (1) no such table: room_table_modification_log
E/ROOM: Cannot run invalidation tracker. Is the db closed?
android.database.sqlite.SQLiteException: no such table: room_table_modification_log
如果我尝试更新任何数据,我会收到这 2 个错误(现在应用确实崩溃了):
java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.
...
E/ROOM: Cannot run invalidation tracker. Is the db closed?
android.database.sqlite.SQLiteException: no such table: room_table_modification_log (code 1 SQLITE_ERROR):
如果我关闭我的应用程序并重新启动它,一切都会正常运行,并且可以毫无错误地查询/更新新数据。我正在使用 Room 2.2.5,在我拥有的不同设备(Android 6 和 10)上看到此错误。
我的代码如下。我在进行还原之前关闭数据库,否则应用程序数据库不会更新。
private void dbImport() {
// DB Backup file to import (e.g. mydatabasebackup.db)
final Uri backupFile = viewModel.getDBImportFile();
String internalDBFile = context.getDatabasePath(APP_DATABASE_NAME).toString();
// Close app database
MyDatabase.destroyInstance();
restoreDatabase(backupFile, internalDBFile);
}
private void restoreDatabase(Uri backupFile, String internalDBFile) {
InputStream inputStream = context.getContentResolver().openInputStream(backupFile);
OutputStream outputStream = new FileOutputStream(internalDBFile);
// Copy backup -> DB
byte[] buffer = new byte[1024];
int read;
while ((read = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, read);
}
inputStream.close();
// Write the output file (this has now copied the file)
outputStream.flush();
outputStream.close();
}
还有我的 Room Db 类
public abstract class MyDatabase extends RoomDatabase {
private static MyDatabase DB_INSTANCE;
public static MyDatabase getDatabase(final Context context) {
if (DB_INSTANCE == null) {
synchronized (MyDatabase.class) {
if (DB_INSTANCE == null) {
DB_INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
MyDatabase.class, APP_DATABASE_NAME)
.addMigrations(new Migration_1_2(context, 1, 2))
.build();
}
}
}
return DB_INSTANCE;
}
public static void destroyInstance() {
if (DB_INSTANCE != null) {
if (DB_INSTANCE.isOpen()) {
DB_INSTANCE.close();
}
DB_INSTANCE = null;
}
}
【问题讨论】:
-
1.您可以尝试在调用
restoreDatabase之前删除-shm和-wal文件吗? 2. 可以添加Migration_1_2吗? -
mcemak - 感谢您的回复。当destroyInstance() 在restoreDatabase() 之前运行时,它会关闭数据库并且那两个文件不再存在——只有.db 文件。关于迁移,我认为发生错误时它并没有运行。我会尝试返回数据库版本,看看是否有什么不同。
标签: android database sqlite import android-room