web-dev-qa-db-ja.com

バックアップルームデータベース

プログラムで部屋のデータベースをバックアップしようとしています。

そのために、データベース全体を含む_.sqlite_ファイルを単にコピーしています

ただし、コピーする前に、部屋が先読みロギングを有効にしているという事実により、データベースを閉じて_-shm_ファイルと_-wal_ファイルをマージする必要があります単一の_.sqlite_ファイルに。 ここで指摘したとおり

RoomDatabase objectで.close()を実行します:

バックアップではすべて正常に動作しますが、後で[INSERT]クエリを実行しようとすると、このエラーが発生します。

_Android.database.sqlite.SQLiteException: no such table: room_table_modification_log (code 1)
_

閉じた後、部屋dbを適切に再度開くにはどうすればよいですか?

PS:RoomDatabase.isOpen()オブジェクトは、trueの前にINSERTを返します

ルームバージョン:_1.1.1-rc1_

15
Alex Busuioc

ルームdbを閉じた後、どうすれば適切に再オープンできますか?

私はその質問に対する答えを持っていないことを残念に思います。

ただし、すべてを元のデータベースファイルに移動することが目的であれば、データベースを閉じる必要はありません。代わりにwal_checkpointプラグマを使用してチェックポイントを強制できます。

次のステートメントをデータベースに対してクエリします。ルームではpragmaがまだサポートされていないため、ここでは生のクエリを使用します(UNKNOWN query typeエラーをトリガーします)。 DAO内で次のクエリを実行します。

@RawQuery
int checkpoint(SupportSQLiteQuery supportSQLiteQuery);

そして、チェックポイントメソッドを呼び出すときは、クエリを使用します。

myDAO.checkpoint(new SimpleSQLiteQuery("pragma wal_checkpoint(full)"));

これ リンクはwal_checkpointが何をするかを明らかにするかもしれません。

16
Anees

より具体的にあなたの質問に答えるために、これは私が私のアプリの一つでルームデータベースをバックアップする方法です。

  1. 外部ストレージの読み取り/書き込みの許可を確認してください。 Appファイルディレクトリに書き込む場合、この手順は無視できます。
  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();
    }
 }
7
Knossos

別の方法として、先読みロギングを使用しないように強制しながら、Roomデータベースをいつでも作成できます。

Room.databaseBuilder(context, db.class, dbName)
    .setJournalMode(JournalMode.TRUNCATE)
    .build();
4
Tjaart

まず、"dbName.db-wal"ファイルからの変更を適用するには、データベースを閉じる必要があります。

その後、すべてのテーブルと最後のデータ変更を含むデータベースをコピーできます

 AppDatabase appDatabase = AppDatabase.getAppDatabase(getApplicationContext());
 appDatabase.close();
0
Shahab Saalami