备份室数据库

Ale*_*ioc 16 sqlite android sqliteopenhelper android-room android-architecture-components

我正在尝试以编程方式备份​​房间数据库.

为此,我只是复制.sqlite包含整个数据库的文件

但是,在复制之前,由于房间已启用提前写入日志,我们必须关闭数据库,以便将-shm文件和-wal文件合并为单个.sqlite文件.正如这里指出的那样

.close()RoomDatabase对象上运行:

一切正常,备份,但是,稍后,当我尝试执行INSERT查询时,我收到此错误:

android.database.sqlite.SQLiteException: no such table: room_table_modification_log (code 1)
Run Code Online (Sandbox Code Playgroud)

关闭后如何才能正确地重新打开房间数据库?

PS:.isOpen()RoomDatabase对象返回trueINSERT

房间版: 1.1.1-rc1

Ber*_*yle 20

关闭后如何才能正确地重新打开房间数据库?

对不起,我对这个问题没有答案.

但是,您不必关闭数据库以将所有内容移动到原始数据库文件.您可以使用wal_checkpoint pragma强制检查点.

根据数据库查询以下语句.

@RawQuery
int checkpoint(SupportSQLiteQuery supportSQLiteQuery);
Run Code Online (Sandbox Code Playgroud)

这个链接可能会对这个问题有所了解.

  • 虽然这不能回答我的问题"如何在关闭它之后正确地重新打开房间数据库?",解决方案解决了我的问题.首先不需要关闭Room数据库.这应该是接受的答案:/sf/ask/3457627841/ (3认同)
  • 先生,您刚刚拯救了世界! (3认同)

Kno*_*sos 8

为了更具体地回答您的问题,这就是我如何在其中一个Apps中备份会议室数据库。

  1. 检查读取/写入外部存储的权限。如果您写入应用程序文件目录,则可以忽略此步骤。
  2. 关闭您的RoomDatabase。在我的情况下,AppDatabase是指一个单例,其中包含用于最初构建会议室数据库的逻辑。AppDatabase.getInstance(this).getDatabase()获取从扩展的单例的当前实例及其当前数据库类RoomDatabase。这本质上称为RoomDatabase.close()
  3. 定义源文件和目标文件,具体取决于备份或还原。我包括shm和wal文件,即使它们是临时文件。
  4. 使用您选择的方法复制文件。FileUtils在这种情况下,请参阅commons-io

代码

if(id == R.id.action_save_db) {
    int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    if(permission == PackageManager.PERMISSION_GRANTED) {
        AppDatabase.getInstance(this).getDatabase().close();

        File db = getDatabasePath("my-db");
        File dbShm = new File(db.getParent(), "my-db-shm");
        File dbWal = new File(db.getParent(), "my-db-wal");

        File db2 = new File("/sdcard/", "my-db");
        File dbShm2 = new File(db2.getParent(), "my-db-shm");
        File dbWal2 = new File(db2.getParent(), "my-db-wal");

        try {
            FileUtils.copyFile(db, db2);
            FileUtils.copyFile(dbShm, dbShm2);
            FileUtils.copyFile(dbWal, dbWal2);
        } catch (Exception e) {
            Log.e("SAVEDB", e.toString());
        }
    } else {
        Snackbar.make(mDrawer, "Please allow access to your storage", Snackbar.LENGTH_LONG)
                .setAction("Allow", view -> ActivityCompat.requestPermissions(this, new String[] {
                        Manifest.permission.WRITE_EXTERNAL_STORAGE
                }, 0)).show();
    }
} else if(id == R.id.action_load_db) {
    int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
    if(permission == PackageManager.PERMISSION_GRANTED) {
        AppDatabase.getInstance(this).getDatabase().close();

        File db = new File("/sdcard/", "my-db");
        File dbShm = new File(db.getParent(), "my-db-shm");
        File dbWal = new File(db.getParent(), "my-db-wal");

        File db2 = getDatabasePath("my-db");
        File dbShm2 = new File(db2.getParent(), "my-db-shm");
        File dbWal2 = new File(db2.getParent(), "my-db-wal");

        try {
            FileUtils.copyFile(db, db2);
            FileUtils.copyFile(dbShm, dbShm2);
            FileUtils.copyFile(dbWal, dbWal2);
        } catch (Exception e) {
            Loge("RESTOREDB", e.toString());
        }
    } else {
        Snackbar.make(mDrawer, "Please allow access to your storage", Snackbar.LENGTH_LONG)
                .setAction("Allow", view -> ActivityCompat.requestPermissions(this, new String[] {
                        Manifest.permission.READ_EXTERNAL_STORAGE
                }, 0)).show();
    }
 }
Run Code Online (Sandbox Code Playgroud)

  • 我在获取实际的数据库文件时没有问题。相反,当我完成备份过程后,在Room db上运行INSERT时出现错误。(包括关闭数据库室的过程) (2认同)
  • 如何将备份文件迁移到最新的新应用程序数据库?因为当我尝试使用上面的代码恢复数据库时,最新的数据库会被删除 (2认同)

Tja*_*art 6

作为替代方案,您始终可以创建 Room 数据库,同时强制它不使用预写日志:

Room.databaseBuilder(context, db.class, dbName)
    .setJournalMode(JournalMode.TRUNCATE)
    .build();
Run Code Online (Sandbox Code Playgroud)