简短形式的问题:从后续文章看来,我应该强调并简化我的问题的核心。核心是:Android DB的其他备份选项似乎存在恢复可能会覆盖数据库中当前数据的风险。是这样的,有没有办法在没有这种风险的情况下进行备份/恢复?
长篇问题:浏览了许多关于在Android上备份SQLite数据库的(相当多)问题,我有一个问题,我找不到答案。< / p>
所有其他备份/恢复讨论都涉及将db文件保存到SD(或在How to backup/restore SQLite database on Android to Dropbox中,保存到云),然后在需要时将其恢复。我担心的是,恢复不会覆盖当前的数据库吗?
我很关心用户何时新安装了他们一直在使用的应用程序(生成新数据),然后想要从应用程序的先前备份导入数据。使用所有其他备份/恢复方法,恢复旧的DB文件似乎会覆盖当前DB文件中的任何新数据。我想要的是一个备份选项,在恢复时,它会将备份中的数据添加到当前数据库中,以使其完整而不会覆盖其中任何其他内容。
其他方法是否这样做?或者,他怀疑,在这种情况下会覆盖吗?
如果他们确实覆盖了,那么我最好的备份选项可能是写出csv或xml文件或其他东西,我希望这些备份讨论能够轻松实现。是否有任何流程可以加快流程并使其变得简单,或者我是否必须手动完成所有流程?如果是这样,建议写入格式以及为什么?
同样,是否有人知道使用BackupAgentHelper的内置Google备份是否会出现同样的覆盖问题?
最后,如果我在任何时候最终都要进行数据迁移(类似于How to Restore SQLite Database from Backup after Core Data model has changed (lightweight migration))我现在应该做什么(我还处于数据库设计阶段),以便将来更容易进行这样的改变相对于此备份过程?
答案 0 :(得分:0)
我认为在您描述的场景中,在不更改(或冲突)“较新”数据的情况下恢复旧数据的问题并不是很难解决。看起来基本上你只是想把旧数据(记录)“添加”到新数据库中,假设旧数据与新数据没有逻辑冲突(也就是说,在语义上可以创建新数据。旧数据)。我认为在恢复期间处理主要关键冲突将是最重要的问题。
我们来看两个案例:
1:您正在使用自动生成数据库的主键值功能(例如,使用SQLite表的AUTOINCREMENT列)。
假设在恢复过程开始之前,“较新的”数据库记录可能使用了主键(ROWID)值1到10。如果您有“旧”数据库记录,其中包含任何主键值(1到10),则只有在要保留这些旧主键值时才会出现问题。要避免这个问题,请不要保留“旧”记录的“旧”主键值 - 从“旧”数据库中读取记录后,只需保存“旧”记录的其他属性(列)的值并让数据库为此“已恢复”记录生成新的主键值。基本上,“旧”记录使用新的主键值保存。如果您担心在“恢复”过程之后保持记录的时间顺序,我建议您还保留一个时间戳列,其值在此过程中不会更改。
2:您正在使用备用机制(UUID,序列生成器等)来生成主键值:
在这种情况下,读取“旧”记录并在将其保存到“较新”数据库之前,将“旧”主键值替换为使用备用机制生成的主键值 - 这将设计为保证“已恢复”记录的主键值相对于预先存在的“较新”记录的唯一性。
为了简化此“恢复”过程的编程工作,尤其是在处理多个表时,您可以使用JDXA之类的ORM。 SDK附带的示例应用程序之一说明了在将数据库升级到较新版本时传输“旧”数据的类似技术。 JDXA还提供了一个方便的序列生成器机制,可以轻松高效地创建可以在持久化之前分配给对象的唯一ID。
答案 1 :(得分:0)
经过不断的研究,我越来越认识到,没有更好的方法解决这个问题。对于简单备份,您可以像许多其他线程一样简单地复制数据库文件,并在未解决的情况下保留对还原问题的覆盖(以及明显的风险兼容性问题:https://stackoverflow.com/a/10842043/3108762)。要获得真正强大的备份,您只需将整个数据库写入XML,然后阅读所有需要的工作。
https://stackoverflow.com/a/34477622/3108762中提到了我发现的唯一更好的替代方案,它引用了新的Android功能Configuring Auto Backup for Apps,但仅适用于Android 6.0及更高版本。我将对此进行测试,但如果它不起作用,并且对于Marshmallow以下的任何内容,它似乎将我的整个数据库写入XML,然后再次读回来是唯一真正强大的方法。 不完全是一个惊喜,但很高兴知道。