Android SQLite 數據庫不丟失數據自動升級流程

       正常我們在開發中經常會遇到sqlite數據庫升級的問題,比如增加字段/刪除字段/表結構重構等等,隨着apk版本的升高,不同版本可能需要對數據庫進行修改,但是要求是數據庫升級不能影響用戶的已存數據,所以今天就來看看數據庫升級流程是怎樣的。

目錄

SQLiteDatabase源碼調用流程

數據庫自動升級流程


  • SQLiteDatabase源碼調用流程

  1. 首先我們需要繼承 SQLiteOpenHelper, 下面是 SQLiteOpenHelper 的源碼註釋:
SQLiteOpenHelper is a helper class to manage database creation and version management.

然後會提示讓我們去重寫他的三個方法:

    public SQLiteOpenHelper(@Nullable Context context, @Nullable String name,
            @Nullable CursorFactory factory, int version) {
        this(context, name, factory, version, null);
        // 傳入我們的數據庫名稱 和 版本號version
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // 創建表
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // 版本升級
    }

       2. 分析以下上述三個方法調用的時機,何時會被調用。

  1. 構造方法--首先我們創建數據庫操作類的時候先走構造方法,通過構造方法會把數據庫名稱和版本號 傳 SQLiteOpenHelper
    當然這只是創建了,數據庫操作類,數據庫還沒有創建。
  2. onCreate() 方法是創建表的,只有第一次纔會走這個方法,首次創建數據庫的時候纔會走,之後就不會走了。
  3. onUpgrade()數據庫升級,這個方法只有構造方法中傳的版本號發生了升級纔會走,所以我們升級的邏輯就在這裏處理。

                    以上只是常用的方法,還有數據庫降級等等方法按需重寫。

       3. 方法調用的源碼流程圖

根據這個流程圖配合我們的源碼更容易理解 sqlite 整個創建流程,這就是整個數據庫版本檢測和獲得db的過程。對整個流程熟悉了之後,接下來我們就好理解數據庫升級。

  • 數據庫自動升級流程

對於升級我們就舉一個例子,從db version 1 升級到db version 2的過程: 

假如我們的表結構是這樣的
* version = 1;
* auto     integer   REAL      REAL
* _id     color     loc_x     loc_y      


* version = 2; 添加了一個 字段 time
* auto     integer   REAL         REAL       REAL
* _id     color     loc_x        loc_y       time

通過分析源碼我們知道數據庫升級是在 onUpgrade() 方法中的,接下來分析升級流程:

  1. 創建臨時緩存表 用於緩存老表裏面的數據
  2. 查詢老表中的數據並且把數據插入到緩存的表中去
  3. 刪除老表,創建新的表結構
  4. 把緩存表數據重新插入到新的表結構中去
  5. 調用查詢,插入檢測是否升級成功
  6. 升級結束

整個流程就這些,接下來把升級的代碼貼上,特別要注意的是升級的流程要放到子線程中去!

@Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //創建臨時緩存表 用於緩存老表裏面的數據
        String createTable = "CREATE TABLE " + snapCachedTableName
                + " (" + CustomColorEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
                + CustomColorEntry.COLUMN_NAME_COLOR + " INTEGER,"
                + CustomColorEntry.COLUMN_NAME_LOCX + " REAL,"
                + CustomColorEntry.COLUMN_NAME_LOCY + " REAL)";
        db.execSQL(createTable);
        //查詢所有的老表數據
        List<CustomColor> colors = getCustomColors(CustomColorEntry.TABLE_NAME,db);
        //把數據插入到緩存的表中去
        for (CustomColor color : colors){
            insertCustomColor(color, snapCachedTableName,db);
        }
        db.execSQL("drop table " + CustomColorEntry.TABLE_NAME);
        //創建新的表結構
        String createNewTable = "CREATE TABLE " + CustomColorEntry.TABLE_NAME
                + " (" + CustomColorEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
                + CustomColorEntry.COLUMN_NAME_COLOR + " INTEGER,"
                + CustomColorEntry.COLUMN_NAME_LOCX + " REAL,"
                + CustomColorEntry.COLUMN_NAME_LOCY + " REAL,"
                + CustomColorEntry.COLUMN_NAME_TIME + " REAL)";
        db.execSQL(createNewTable);
        //查詢所有的緩存表中的數據
        List<CustomColor> cachedColors = getCustomColors(snapCachedTableName,db);
        //把數據插入到新的表中去
        for (CustomColor color : cachedColors){
            insertCustomColor(color, CustomColorEntry.TABLE_NAME,db);
        }
        db.execSQL("drop table " + snapCachedTableName);
    }

傳送門github:https://github.com/WangRain1/DbUpgradeDemo 大家給點支持,笑嘻嘻

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章