【问题标题】:Android room database won't export all the dataAndroid房间数据库不会导出所有数据
【发布时间】:2018-08-29 21:14:51
【问题描述】:

我正在尝试设置 Room 数据库备份功能。 问题是 sql 数据库文件在下载后不包含应用程序中的最新数据集。它总是错过一些最近的记录。 有没有导出房间数据库的正确方法? 附言在使用 sqliteHelper 处理我的数据库时,我没有遇到类似的问题,所以我想它一定与 Room 有关。

我的做法:

@Throws(IOException::class)
private fun copyAppDbToDownloadFolder(address: String) {
    val backupDB = File(address, "studioDb.db") 
    val currentDB = applicationContext.getDatabasePath(StudioDatabase.DB_NAME)
    if (currentDB.exists()) {
        val src = FileInputStream(currentDB).channel
        val dst = FileOutputStream(backupDB).channel
        dst.transferFrom(src, 0, src.size())
        src.close()
        dst.close()
    }
}

【问题讨论】:

标签: android android-sqlite android-room android-sql


【解决方案1】:

你需要使用

JournalMode.TRUNCATE

在您的 AppDatabase.java 中:

private static AppDatabase sInstance;

public static AppDatabase getDatabase(final Context context) {
    if (sInstance == null) {
        synchronized (AppDatabase.class) {
            if (sInstance == null) {
                sInstance = Room.databaseBuilder(context, AppDatabase.class, DATABASE_NAME)
                        .setJournalMode(JournalMode.TRUNCATE)
                        .build();
            }
        }
    }
    return sInstance;
}

此方法不会创建阻碍房间数据库导出的 db.bad 和 db.wal 文件。

用于导出数据库文件:

链接:Exporting db with creating folder on daily basis

【讨论】:

    【解决方案2】:

    我有同样的问题。您不需要复制 wal (预写日志文件),它是一个临时文件。根据documentation,我们需要在导入或导出数据库之前关闭与数据库的所有连接。这解决了我的问题,现在我只需要复制主数据库文件。

    数据库类示例:

    public abstract class AppDB extends RoomDatabase {    
    
        private static final Object sLock = new Object();
    
        private static AppDB INSTANCE;
    
        // create new database connection
        public static AppDB getInstance(final Context context) {
            synchronized (sLock) {
                if (INSTANCE == null) {
                    INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDB.class, "packagename")                    
                        .build();
                    }
                return INSTANCE;
            }
        }
    
        // close database
        public static void destroyInstance(){
            if (INSTANCE.isOpen()) INSTANCE.close();
            INSTANCE = null;
        }
    }
    

    【讨论】:

    • 谢谢,这是个好消息!以及如何关闭与数据库的所有连接?
    • 只需在所有房间数据库对象上调用 close() 函数。
    • @MuzammilHusnain "所有房间数据库对象" 应该只有一个开放数据库实例。
    • @rupinderjeet 是的,理想情况下应该只有一个开放数据库的实例。
    • 问题是,如果您重新打开数据库并尝试执行任何操作,都会失败,如下所述:stackoverflow.com/questions/50987119/backup-room-database
    【解决方案3】:

    我已经解决了。在导出(保存)您使用 Room 处理的 sql 数据库时,您必须同时导出(然后导入)your_database.bd 和 your_database.wal 文件。后来是日记,afaiu保存最新记录。

    【讨论】:

    • 两个文件的路径是什么,请解释我有同样的问题
    • @Lokesh 有几种方法可以获取数据库路径。我正在使用以下内容:val currentDBPath = "//data//" + packageName + "//databases//" + DatabaseHelper.DATABASE_NAME + "" val backupDBPath = DatabaseHelper.DATABASE_NAME + ".db" val currentDB = File(data, currentDBPath)
    • 另一种方法是这样(注意我用它来获取.wal文件路径):val currentdbW = applicationContext.getDatabasePath(StudioDatabase.DB_NAME + "-wal")
    【解决方案4】:

    kotlin:这对我有用

    private fun exportDb() {
        val TABLE_NAME = "order_table"
    
        val exportDir = File(getExternalStorageDirectory(), "/CSV")// your path where you want save your file
        if (!exportDir.exists()) {
            exportDir.mkdirs()
        }
    
        val file = File(exportDir, "$TABLE_NAME.csv")
    
    
        try {
            file.createNewFile()
            val db: MenuItemsDatabase = MenuItemsDatabase.getDatabase(requireActivity())
            val csvWrite = CSVWriter(FileWriter(file))
            val curCSV: Cursor = db.query("SELECT * FROM order_table", null)
            csvWrite.writeNext(curCSV.getColumnNames())
            while (curCSV.moveToNext()) {
                //Which column you want to exprort
                   val arrStr = arrayOfNulls<String>(curCSV.getColumnCount())
            
                for (i in 0 until curCSV.getColumnCount() - 1) arrStr[i] = curCSV.getString(i)
                csvWrite.writeNext(arrStr)
            }
            csvWrite.close()
            curCSV.close()
            Toast.makeText(context, "Exported", Toast.LENGTH_SHORT).show()
    
        } catch (sqlEx: java.lang.Exception) {
            //Log.e("Payment fragment", "Exported error", sqlEx)
            Toast.makeText(context, "Exported error", Toast.LENGTH_SHORT).show()
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-11-11
      • 1970-01-01
      • 2022-01-24
      • 1970-01-01
      • 2020-05-06
      • 2018-12-05
      • 2018-08-17
      • 2021-08-13
      • 1970-01-01
      相关资源
      最近更新 更多