房间DB文件导入错误('没有这样的表:ROOM_TABLE_MODIFICATION_LOG') [英] Room DB file import error ('no such table: room_table_modification_log')

查看:47
本文介绍了房间DB文件导入错误('没有这样的表:ROOM_TABLE_MODIFICATION_LOG')的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试让我的应用程序备份和还原其DB文件(例如mydatabase ase.db)(&;Restore)。备份运行良好-它导出单个.db文件。它不会导出-shm/-wal文件,因为我运行了一个‘杂注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 

如果我随后尝试更新任何数据,则会收到以下两个错误(现在应用程序确实崩溃了):

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();
    }

和My 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;
        }
    }

推荐答案

回答我自己的问题,以防其他人遇到同样的问题。

我在BackupActivity中导入DB文件,一旦完成,它将返回到MainActivity(它查询数据库并显示数据)。回到MainActivity,我重新创建了我的LiveData观察器,并再次重新运行我的DB查询,以便从新导入的数据库中获取数据。问题似乎是我没有为新数据库重新创建回购/DAO。由于IF/NULL检查,ViewModel仍保留以前的回购引用。

ViewModel

   LiveData<User> userLD = getUserRepo().getUser(); 
    
   private UserRepo getUserRepo() {
        if (userRepo == null) {
            userRepo = new UserRepo(getApplication());
        }
        return userRepo;
    }

用户回购

    // Constructor
    public UserRepo(Application application) {
        super();
        MyDatabase db = MyDatabase.getDatabase(application);
        dao = db.getUserDao();
    }

通过重新创建UserRepo(取消IF/NULL检查),新的Repo/DAO基于新的DB,现在一切正常。

另一个同样有效的解决方案是,在执行DB导入之后从BackupActivity返回时,我使用这些标志从头重新启动MainActivity(以完成堆栈中的所有活动-包括BackupActivity)。

Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

这篇关于房间DB文件导入错误(&#39;没有这样的表:ROOM_TABLE_MODIFICATION_LOG&#39;)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆