Android學習筆記----升級SQLite數據庫的最佳寫法

/***************************************************************************************/
升級數據庫的最佳寫法

關於SQLite數據庫的基本用法,可以閱讀我的上篇博客  Android學習筆記----SQLite數據庫的基本用法

每一個數據庫版本都會對應一個版本號,當指定的數據庫版本號大於當前數據庫版本號的時候,就會進入到 onUpgrade()方法中去執行更新操作。這裏需要爲每一個版本號賦予它各自改變的內容,然後在onUpgrade()方法中對當前數據庫的版本號進行判斷,再執行相應的改變就可以了。接着就讓我們來模擬一個數據庫升級的案例,還是由 MyDatabaseHelper 類來對數據庫進行管理。

第一版的程序要求非常簡單, 只需要創建一張 Book 表, MyDatabaseHelper 中的代碼如下所示:

public class MyDatabaseHelper extends SQLiteOpenHelper {

    public static final String CREATE_BOOK = "create table Book ("+ "id integer primary key autoincrement, "
        + "author text, "
        + "price real, "
        + "pages integer, "
    + "name text)";

    public MyDatabaseHelper(Context context, String name, CursorFactory factory, int version) {
        super(context, name, factory, version);
    }
    
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK);
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}



不過, 幾星期之後又有了新需求,這次需要向數據庫中再添加一張 Category 表。於是,修改 MyDatabaseHelper 中的代碼,如下所示:

public class MyDatabaseHelper extends SQLiteOpenHelper {
    public static final String CREATE_BOOK = "create table Book ("
        + "id integer primary key autoincrement, "
        + "author text, "
        + "price real, "
        + "pages integer, "
        + "name text)";
        
        public static final String CREATE_CATEGORY = "create table Category ("
        + "id integer primary key autoincrement, "
        + "category_name text, "
        + "category_code integer)";

    public MyDatabaseHelper(Context context, String name,CursorFactory factory, int version) {
            super(context, name, factory, version);
    }
    
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK);
        db.execSQL(CREATE_CATEGORY);
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        switch (oldVersion) {
            case 1:
                db.execSQL(CREATE_CATEGORY);
            default:
       }
    }
}

可以看到,在 onCreate()方法裏我們新增了一條建表語句,然後又在 onUpgrade()方法中添加了一個 switch 判斷,如果用戶當前數據庫的版本號是 1,就只會創建一張 Category 表。這樣當用戶是直接安裝的第二版的程序時,就會將兩張表一起創建。而當用戶是使用第二版的程序覆蓋安裝第一版的程序時,就會進入到升級數據庫的操作中,此時由於 Book 表已經存在了,因此只需要創建一張 Category 表即可。但是沒過多久,新的需求又來了,這次要給 Book 表和 Category 表之間建立關聯,需要在 Book 表中添加一個 category_id 的字段。再次修改 MyDatabaseHelper 中的代碼,如下所示:

public class MyDatabaseHelper extends SQLiteOpenHelper {
        public static final String CREATE_BOOK = "create table Book ("
            + "id integer primary key autoincrement, "
            + "author text, "
            + "price real, "
            + "pages integer, "
            + "name text, "
            + "category_id integer)";
        
        public static final String CREATE_CATEGORY = "create table Category ("
            + "id integer primary key autoincrement, "
            + "category_name text, "
            + "category_code integer)";

        public MyDatabaseHelper(Context context, String name,CursorFactory factory, int version) {
                super(context, name, factory, version);
        }
        
        @Override
        public void onCreate(SQLiteDatabase db) {
               db.execSQL(CREATE_BOOK);
                db.execSQL(CREATE_CATEGORY);
        }
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
               switch (oldVersion) {
                    case 1:
                        db.execSQL(CREATE_CATEGORY);
                    case 2:
                        db.execSQL("alter table Book add column category_id integer");
                    default:
           }
    }
}

可以看到,首先我們在 Book 表的建表語句中添加了一個 category_id 列,這樣當用戶直接安裝第三版的程序時,這個新增的列就已經自動添加成功了。然而,如果用戶之前已經安裝了某一版本的程序,現在需要覆蓋安裝,就會進入到升級數據庫的操作中。在 onUpgrade()方法裏,我們添加了一個新的 case,如果當前數據庫的版本號是 2,就會執行 alter 命令來爲Book 表新增一個 category_id 列。這裏請注意一個非常重要的細節, switch 中每一個 case 的最後都是沒有使用 break 的,爲什麼要這麼做呢?這是爲了保證在跨版本升級的時候,每一次的數據庫修改都能被全部執行到。比如用戶當前是從第二版程序升級到第三版程序的,那麼 case 2 中的邏輯就會執行。而如果用戶是直接從第一版程序升級到第三版程序的,那麼 case 1 和 case 2 中的邏輯都會執行。使用這種方式來維護數據庫的升級,不管版本怎樣更新,都可以保證數據庫的表結構是最新的,而且表中的數據也完全不會丟失了。

注:此博客摘自郭琳老師的《Android第一行代碼》一書中,在次表示感謝。


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