掘金:https://juejin.im/user/1785262612681997
博客:http://www.cnblogs.com/linguanh/
GitHub : https://github.com/af913337456/
腾讯云专栏: https://cloud.tencent.com/developer/user/1148436/activities
开源地址:github.com/af913337456…
本文不会花时间去谈 greenDao 是什么
使用 greenDao 作为线上APP 的本地 orm 框架时候,总有数据库表要更新的一天,或早或迟。
目录- 出问题的的情形
- 几个事实
- 解决方案
- 代码简述
- 产品级别的可能错误
- 你的顾虑
- 字段添加,导致旧表格字段与新的不匹配引发 android.database.sqlite.SQLiteException 类异常。
- 服务端数据返回无法与就表格匹配,无法进行插入操作
第一个情况会直接导致 APP 闪退掉,第二种就是数据不匹配。
几个事实- GreenDao 目前的 3.+ 版,自动生成的代码的升级方式都是先删除原来的表格,再创建新的
public static class DevOpenHelper extends OpenHelper {
…
@Override
public void onUpgrade(Database db, int oldVersion, int newVersion) {
Log.i(“greenDAO”, “Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables”);
dropAllTables(db, true); // 删除-----①
onCreate(db);
}
}
- 凡是自动生成的代码文件,例如 xxxDao.java 类的,都会在每一次 build 的时候重新被生成,意味着个人的内嵌修改总是无效,因为总是覆盖你的。
- 数据库的升级方式需求更多是需要往后兼容的,旧数据不能丢失
自定义升级策略。 思路参考
在上面的基础上做出如下步骤总结: (看不懂的看下面的符号描述)
- 创建之前旧表中不存在的新表
- 创建中间表 & 把旧表的数据迁移到中间表
- 把旧表全部删除
- 创建所有新表
- 把中间表的数据迁移到新表 & 删除中间表
对应上面的步骤描述:
- A -> A + B , old: A , new: B
- use (A+B) -> create temp (A’+B’) & insert data
- drop (A+B) , contain old datas
- create (A+B) , abs empty tables
- restore data to (A+B) from (A’+B’) then drop (A’+B’)
基于上面的二次修改和拓展
-
GreenDaoCompatibleUpdateHelper.java 顾名思义,兼容旧表性质的 greenDao 数据库升级,不会造成旧表的数据丢失
-
拓展了最终的成功和失败的回调
-
添加了错误日志的处理
-
解决了字段名称的冲突 bug,例如 delete 之类
-
MyGreenDaoDbHelper.java 自定义的 dbHelper,重载 onUpgrade
if (oldVersion < newVersion) {
Log.e(“MyGreenDaoDbHelper”,“进行数据库升级”);
new GreenDaoCompatibleUpdateHelper()
.setCallBack(
new GreenDaoCompatibleUpdateHelper.GreenDaoCompatibleUpdateCallBack() {
@Override
public void onFinalSuccess() {
Log.e(“MyGreenDaoDbHelper”,“进行数据库升级 ===> 成功”);
}
@Override
public void onFailedLog(String errorMsg) {
Log.e(“MyGreenDaoDbHelper”,"升级失败日志 ===> "+errorMsg);
}
}
)
.compatibleUpdate(
db,
PostBeanDao.class,
MatterUserBeanDao.class,
PropsBeanDao.class,
ChannelChatsBeanDao.class,
JoinToChannelReqBeanDao.class
);
Log.e(“MyGreenDaoDbHelper”,“进行数据库升级–完成”);
}
public final class GreenDaoCompatibleUpdateHelper {
public interface GreenDaoCompatibleUpdateCallBack{
void onFinalSuccess();
void onFailedLog(String errorMsg);
}
private static GreenDaoCompatibleUpdateCallBack callBack;
@SuppressWarnings(“all”)
public void compatibleUpdate(SQLiteDatabase sqliteDatabase, Class extends AbstractDao, ?>>… daoClasses) {
StandardDatabase db = new StandardDatabase(sqliteDatabase);
restoreData_fromTempTableTonewTable(db, daoClasses);
if(callBack != null)
callBack.onFinalSuccess();
callBack = null;
}
public GreenDaoCompatibleUpdateHelper setCallBack(GreenDaoCompatibleUpdateCallBack callBack1){
callBack = callBack1;
return this;
}



