web-dev-qa-db-fra.com

Base de données de la salle de sauvegarde

J'essaye de sauvegarder une base de données de pièce par programme.

Pour cela, je copie simplement le fichier .sqlite qui contient la base de données entière.

Mais, avant la copie, en raison du fait que la pièce dispose de la fonction {journalisation en écriture anticipée}, nous devons fermer la base de données pour que le fichier -shm et le fichier -wal soient fusionnés en un seul fichier .sqlite. Comme indiqué ici

Je lance .close() sur RoomDatabase object: 

Tout fonctionne bien avec la sauvegarde, MAIS, plus tard, lorsque j'essaie d'exécuter une requête INSERT, j'obtiens cette erreur: 

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

Comment puis-je rouvrir correctement la base de données après l'avoir fermée?

PS: .isOpen() sur un objet RoomDatabase renvoie true avant INSERT

Version de la salle: 1.1.1-rc1

13
Alex Busuioc

Comment puis-je rouvrir correctement la base de données après l'avoir fermée?

Je suis désolé de ne pas avoir de réponse à cette question.

Mais vous n'avez pas besoin de fermer la base de données pour tout déplacer dans le fichier de base de données d'origine. Vous pouvez forcer un point de contrôle en utilisant le pragma wal_checkpoint.

Interrogez l'instruction suivante sur la base de données.

pragma wal_checkpoint(full)

This link peut éclairer un peu le sujet.

7
Anees

Pour répondre plus précisément à votre question, voici comment je sauvegarde la base de données de la salle dans l’une de mes applications.

  1. Vérifiez l'autorisation de lire/écrire sur le stockage externe. Vous pouvez ignorer cette étape si vous écrivez dans votre répertoire de fichiers d'application.
  2. Fermez votre RoomDatabase. Dans mon cas, AppDatabase fait référence à un singleton qui contient une logique pour la construction initiale de la base de données de salles. AppDatabase.getInstance(this).getDatabase() obtient l'instance actuelle du singleton et sa classe de base de données actuelle, qui s'étend de RoomDatabase. Cela appelle essentiellement RoomDatabase.close().
  3. Définissez les fichiers source et cible en fonction de la sauvegarde ou de la restauration. J'inclus les fichiers shm et wal, même s'il s'agit de fichiers temporaires.
  4. Copiez les fichiers avec la méthode de votre choix. FileUtils dans ce cas, fait référence à commons-io.

Le code

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

Alternativement, vous pouvez toujours créer votre base de données Room tout en le forçant à ne pas utiliser la journalisation en écriture anticipée:

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

Tout d'abord, la base de données doit être fermée pour appliquer les modifications du fichier "dbName.db-wal".

Ensuite, vous pouvez copier la base de données avec toutes les tables et les dernières modifications de données

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