プログラムで部屋のデータベースをバックアップしようとしています。
そのために、データベース全体を含む_.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
_
ルームdbを閉じた後、どうすれば適切に再オープンできますか?
私はその質問に対する答えを持っていないことを残念に思います。
ただし、すべてを元のデータベースファイルに移動することが目的であれば、データベースを閉じる必要はありません。代わりにwal_checkpoint
プラグマを使用してチェックポイントを強制できます。
次のステートメントをデータベースに対してクエリします。ルームではpragma
がまだサポートされていないため、ここでは生のクエリを使用します(UNKNOWN query type
エラーをトリガーします)。 DAO内で次のクエリを実行します。
@RawQuery
int checkpoint(SupportSQLiteQuery supportSQLiteQuery);
そして、チェックポイントメソッドを呼び出すときは、クエリを使用します。
myDAO.checkpoint(new SimpleSQLiteQuery("pragma wal_checkpoint(full)"));
これ リンクはwal_checkpoint
が何をするかを明らかにするかもしれません。
より具体的にあなたの質問に答えるために、これは私が私のアプリの一つでルームデータベースをバックアップする方法です。
RoomDatabase
を閉じます。私の場合、AppDatabase
は、最初にルームデータベースを構築するためのロジックを含むシングルトンを指します。 AppDatabase.getInstance(this).getDatabase()
は、シングルトンの現在のインスタンスと、RoomDatabase
から拡張された現在のデータベースクラスを取得します。これは本質的にRoomDatabase.close()
を呼び出します。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();
}
}
別の方法として、先読みロギングを使用しないように強制しながら、Roomデータベースをいつでも作成できます。
Room.databaseBuilder(context, db.class, dbName)
.setJournalMode(JournalMode.TRUNCATE)
.build();
まず、"dbName.db-wal"
ファイルからの変更を適用するには、データベースを閉じる必要があります。
その後、すべてのテーブルと最後のデータ変更を含むデータベースをコピーできます
AppDatabase appDatabase = AppDatabase.getAppDatabase(getApplicationContext());
appDatabase.close();