作者:林冠宏 / 指尖下的幽灵
掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8
博客:http://www.cnblogs.com/linguanh/
GitHub : https://github.com/af913337456/
腾讯云专栏: https://cloud.tencent.com/developer/user/1148436/activities
一个能帮助你成功升级基于 greenDao 创建的数据库而不会丢失之前数据的工具 A helper which can help you to update you database without lost your old datas, simple to use , enjoy.
https://github.com/af913337456/LghGreenDaoCompatibleUpdateHelper
android.database.sqlite.SQLiteException
类异常。第一个情况会直接导致 APP 闪退掉,第二种就是数据不匹配。
先删除原来的表格,再创建新的
/** WARNING: Drops all table on Upgrade! Use only during development. */ 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 的时候重新被生成,意味着个人的内嵌修改总是无效,因为总是覆盖你的。自定义升级策略。 思路参考
在上面的基础上做出如下步骤总结: (看不懂的看下面的符号描述
)
对应上面的步骤描述:
基于上面的二次修改和拓展
GreenDaoCompatibleUpdateHelper.java
顾名思义,兼容旧表性质的 greenDao 数据库升级,不会造成旧表的数据丢失
MyGreenDaoDbHelper.java
自定义的 dbHelper,重载 onUpgradeif (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);
/** 创建之前旧表中不存在的新表 */
if(!generateNewTablesIfNotExists_withNoExchangeData(db, daoClasses))
return;
/** 创建中间表 & 把旧表的数据迁移到中间表 */
if(!generateTempTables_withExchangeDataFromOldTable(db, daoClasses))
return;
/** 把旧表全部删除 */
if(!dropAllTables(db, true, daoClasses))
return;
/** 创建所有新表 */
if(!createAllTables_withNoExchangeData(db, false, daoClasses))
return;
/** 把中间表的数据迁移到新表 & 删除中间表 */
restoreData_fromTempTableToNewTable(db, daoClasses);
if(callBack != null)
callBack.onFinalSuccess();
callBack = null;
}
public GreenDaoCompatibleUpdateHelper setCallBack(GreenDaoCompatibleUpdateCallBack callBack1){
callBack = callBack1;
return this;
}
...... // 去 gitHub 下载完整代码
}
public class MyGreenDaoDbHelper extends DaoMaster.DevOpenHelper {
public MyGreenDaoDbHelper(Context context, String name) {
super(context, name);
}
public MyGreenDaoDbHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
super(context, name, factory);
}
@Override
@SuppressWarnings("all")
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
super.onUpgrade(db, oldVersion, newVersion);
Log.e("MyGreenDaoDbHelper", "----"+oldVersion + "---先前和更新之后的版本---" + newVersion+"----");
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","进行数据库升级--完成");
}
}
@Override
public void onUpgrade(Database db, int oldVersion, int newVersion) {
// 不要调用父类的,它默认是先删除全部表再创建
// super.onUpgrade(db, oldVersion, newVersion);
}
}
SQLiteConstraintException: NOT NULL constraint failed
错误,解决方法,采用 Integer Boolean 类型替换,这个你只能妥协,因为 greenDao 作者不屑于在你建表的时候提供默认值方法。详情可以去看看 issue1, 答: sqlLite 的源码里面调用 onUpdrade
方法的入口皆加上了同步琐
,这样不会造成在升级中还能让你去读写的情况。
这点设计得非常优秀!表太多的,几百张?那么就放入子线程升级。
2, 答: 我已经使用到线上多个APP , 且成功运行至今。