Backup Room database

后端 未结 7 765
夕颜
夕颜 2020-12-08 01:41

I\'m trying to backup a room database programmatically.

For that, I\'m simply copying the .sqlite file that contains the whole database

But, bef

相关标签:
7条回答
  • 2020-12-08 01:49

    It already has been answered above. No need to close/re-open database.

    I am using MVVM pattern in my android app to back up db file to upload it to google drive. Just want to summarise the solution that worked for me:

    Mention below code in your DAO file:

    @RawQuery
        int checkpoint(SupportSQLiteQuery supportSQLiteQuery);
    

    Mention below code in your repository file:

        /* Android database has three files under /data/data/com.package.app/databases/
        ** test.db, test.db-shm, test.db-wal - those extra files have recent commits.
        ** To merge data from other shm and wal files to db, run following method - useful before taking backup.
        */
        void checkPoint() {
            ItemRoomDatabase.databaseWriteExecutor.execute(() -> {
               itemDao.checkpoint(new SimpleSQLiteQuery("pragma wal_checkpoint(full)"));
            });
        }
    

    mention following in your ViewModel:

    public void checkPoint() {
          itemRepository.checkPoint();
    }
    

    Now you can call this method just before doing backup from your Activity file

    ItemViewModel itemViewModel = new ViewModelProvider(this).get(ItemViewModel.class);
    itemViewModel.checkPoint();
    
    0 讨论(0)
  • 2020-12-08 01:54

    How can I properly re-open room db after I close it?

    I am sorry that that this doesn't answer that question.

    But if moving everything to the original database file is what you want to do, then you don't have to close the database in the first place. You can force a checkpoint using the wal_checkpoint pragma instead.

    Query the following statement against the database. We use raw queries here as pragma is not yet supported by Room (it will trigger a UNKNOWN query type error). Have this query inside of your DAO:

    @RawQuery
    int checkpoint(SupportSQLiteQuery supportSQLiteQuery);
    

    And then when you call the checkpoint method, use the query then:

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

    This link may shed some light on what wal_checkpoint does.

    0 讨论(0)
  • 2020-12-08 01:56

    I am using this library for backup and re store room database and its super easy to use.

    https://github.com/salehyarahmadi/RoomDatabaseBackupAndRestore
    

    Thanks to salehyarahmadi

    0 讨论(0)
  • 2020-12-08 02:00

    First, the database must be closed to apply changes from the "dbName.db-wal" file.

    Then you can copy the database with all tables and last data changes

     AppDatabase appDatabase = AppDatabase.getAppDatabase(getApplicationContext());
     appDatabase.close();
    
    0 讨论(0)
  • 2020-12-08 02:05

    To more specifically answer your question, this is how I backup the room database in one of my Apps.

    1. Check for permission to read from / write to the external storage. You can ignore this step if you write to your App files directory.
    2. Close your RoomDatabase. In my case AppDatabase refers to a singleton that contains logic for building the room database initially. AppDatabase.getInstance(this).getDatabase() gets the current instance of the singleton, and its current database class, that extends from RoomDatabase. This essentially calls RoomDatabase.close().
    3. Define the source and destination files, depending on backing up or restoring. I include shm and wal files, even though they are temporary files.
    4. Copy the files with your method of choice. FileUtils in this case, refers to commons-io.

    The 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();
        }
     }
    
    0 讨论(0)
  • 2020-12-08 02:09

    As an alternative, you can always create your Room database while forcing it not to use write ahead logging:

    Room.databaseBuilder(context, db.class, dbName)
        .setJournalMode(JournalMode.TRUNCATE)
        .build();
    
    0 讨论(0)
提交回复
热议问题