做者:林冠宏 / 指尖下的幽靈java
掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8android
博客:http://www.cnblogs.com/linguanh/git
GitHub : https://github.com/af913337456/github
騰訊雲專欄: https://cloud.tencent.com/developer/user/1148436/activitiessql
開源地址:github.com/af913337456…數據庫
使用 greenDao 做爲線上APP 的本地 orm 框架時候,總有數據庫表要更新的一天,或早或遲。框架
android.database.sqlite.SQLiteException
類異常。第一個狀況會直接致使 APP 閃退掉,第二種就是數據不匹配。ide
先刪除原來的表格,再建立新的
/** 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 的時候從新被生成,意味着我的的內嵌修改老是無效,由於老是覆蓋你的。自定義升級策略。 思路參考ui
在上面的基礎上作出以下步驟總結: (看不懂的看下面的符號描述
)this
對應上面的步驟描述:
基於上面的二次修改和拓展
GreenDaoCompatibleUpdateHelper.java
顧名思義,兼容舊錶性質的 greenDao 數據庫升級,不會形成舊錶的數據丟失
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);
/** 建立以前舊錶中不存在的新表 */
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 , 且成功運行至今。