Android數據庫高手祕籍(三)——使用LitePal升級表

在上一篇文章中,咱們學習了LitePal的基本用法,體驗了使用框架來進行建立表操做的便利。然而你們都知道,建立表只是數據庫操做中最基本的一步而已,咱們在一開始建立的表結構,隨着需求的變動,到了後期是極有可能須要修改的。所以,升級表的操做對於任何一個項目也是相當重要的,那麼今天咱們就一塊兒來學習一下,在Android傳統開發當中升級表的方式,以及使用LitePal來進行升級表操做的用法。若是你尚未看過前一篇文章,建議先去參考一下 Android數據庫高手祕籍(二)——建立表和LitePal的基本用法 。java

LitePal的項目地址是:https://github.com/LitePalFramework/LitePalgit

傳統的升級表方式

上一篇文章中咱們藉助MySQLiteHelper已經建立好了news這張表,這也是demo.db這個數據庫的第一個版本。然而,如今需求發生了變動,咱們的軟件除了能看新聞以外,還應該容許用戶評論,因此這時就須要對數據庫進行升級,添加一個comment表。程序員

該怎麼作呢?添加一個comment表的建表語句,而後在onCreate()方法中去執行它?沒錯,這樣的話,兩張表就會同時建立了,代碼以下所示:github

public class MySQLiteHelper extends SQLiteOpenHelper {
     
    public static final String CREATE_NEWS = "create table news ("
            + "id integer primary key autoincrement, "
            + "title text, "
            + "content text, "
            + "publishdate integer,"
            + "commentcount integer)";
     
    public static final String CREATE_COMMENT = "create table comment ("
            + "id integer primary key autoincrement, "
            + "content text)";
 
    public MySQLiteHelper(Context context, String name, CursorFactory factory,
            int version) {
        super(context, name, factory, version);
    }
 
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_NEWS);
        db.execSQL(CREATE_COMMENT);
    }
 
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
 
}

這對於第一次安裝咱們軟件的用戶來講是徹底能夠正常工做的,可是若是有的用戶已經安裝過上一版的軟件,那麼很遺憾,comment表是建立不出來的,由於以前數據庫就已經建立過了,onCreate()方法是不會從新執行的。數據庫

 

對於這種狀況咱們就要用升級的方式來解決了,看到MySQLiteHelper構造方法中的第四個參數了嗎,這個就是數據庫版本號的標識,每當版本號增長的時候就會調用onUpgrade()方法,咱們只須要在這裏處理升級表的操做就好了。比較簡單粗暴的方式是將數據庫中現有的全部表都刪除掉,而後從新建立,代碼以下所示:數據結構

public class MySQLiteHelper extends SQLiteOpenHelper {
     
    ......
 
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_NEWS);
        db.execSQL(CREATE_COMMENT);
    }
 
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("drop table if exists news");
        onCreate(db);
    }
 
}

能夠看到,當數據庫升級的時候,咱們先把news表刪除掉,而後從新執行了一次onCreate()方法,這樣就保證數據庫中的表都是最新的了。app

 

可是,若是news表中原本已經有數據了,使用這種方式升級的話,就會致使表中的數據所有丟失,因此這並非一種值得推薦的升級方法。那麼更好的升級方法是什麼樣的呢?這就稍微有些複雜了,須要在onUpgrade()方法中根據版本號加入具體的升級邏輯,咱們來試試來吧。好比以前的數據庫版本號是1,那麼在onUpgrade()方法中就能夠這樣寫:框架

public class MySQLiteHelper extends SQLiteOpenHelper {
 
    ......
 
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_NEWS);
        db.execSQL(CREATE_COMMENT);
    }
 
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        switch (oldVersion) {
        case 1:
            db.execSQL(CREATE_COMMENT);
        default:
        }
    }
 
}

能夠看到,這裏在onUpgrade()方法中加入了一個switch判斷,若是oldVersion等於1,就再建立一個comment表。如今只須要調用以下代碼,表就能夠獲得建立或升級了:ide

SQLiteOpenHelper dbHelper = new MySQLiteHelper(this, "demo.db", null, 2);
SQLiteDatabase db = dbHelper.getWritableDatabase();

這裏咱們將版本號加1,若是用戶是從舊版本升級過來的,就會新增一個comment表,而若是用戶是直接安裝的新版本,就會在onCreate()方法中把兩個表一塊兒建立了。學習

 

OK,如今軟件的第二版本也發佈出去了,但是就在發佈不久以後,忽然發現comment表中少了一個字段,咱們並無記錄評論發佈的時間。沒辦法,只好在第三版中修復這個問題了,那咱們該怎麼樣去添加這個字段呢?主要須要修改comment表的建表語句,以及onUpgrade()方法中的邏輯,代碼以下所示:

public class MySQLiteHelper extends SQLiteOpenHelper {
 
    ......
 
    public static final String CREATE_COMMENT = "create table comment ("
            + "id integer primary key autoincrement, "
            + "content text, "
            + "publishdate integer)";
 
    ......
 
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        switch (oldVersion) {
        case 1:
            db.execSQL(CREATE_COMMENT);
            break;
        case 2:
            db.execSQL("alter table comment add column publishdate integer");
            break;
        default:
        }
    }
 
}

能夠看到,在建表語句當中咱們新增了publishdate這一列,這樣當執行onCreate()方法去建立表的時候,comment表中就會有這一列了。那麼若是是從舊版本升級過來的呢?也沒有問題,咱們在onUpgrade()方法中已經把升級邏輯都處理好了,當oldVersion等於2的時候,會執行alter語句來添加publishdate這一列。如今調用如下代碼來建立或升級數據庫:

SQLiteOpenHelper dbHelper = new MySQLiteHelper(this, "demo.db", null, 3);
SQLiteDatabase db = dbHelper.getWritableDatabase();

將數據庫版本號設置成3,這樣就能夠保證數據庫中的表又是最新的了。

如今咱們已經學習了新增表和新增列這兩種升級方式,那麼若是是某張表中的某一列已經沒有用了,我想把這一列刪除掉該怎麼寫呢?很遺憾,SQLite並不支持刪除列的功能,對於這狀況,多數軟件採起的做法是無視它,反正之後也用不到它了,留着也佔不了什麼空間,因此針對於這種需求,確實沒什麼簡單的解決辦法。

這大概就是傳統開發當中升級數據庫表的方式了,雖然說能寫出這樣的代碼表示你已經對數據庫的升級操做理解的比較清楚了,但隨着版本愈來愈多,onUpgrade()方法中的邏輯也會變得愈發複雜,稍微一不留神,也許就會產生錯誤。所以,若是能讓代碼自動控制升級邏輯,而不是由人工來管理,那就是再好不過了,那麼下面咱們就來學習一下怎樣使用LitePal來進行升級表的操做。

使用LitePal升級表

經過上一篇文章的學習,咱們已經知道LitePal是一款ORM模式的框架了,已經熟悉建立表流程的你,相信對於升級表也必定會輕車熟路的。那麼爲了模仿傳統升級表方式中的需求,如今咱們也須要建立一張comment表。第一步該怎麼辦呢?相信你也許早就已經猜到了,那固然是先建立一個Comment類了,以下所示:

package com.example.databasetest.model;
 
public class Comment {
     
    private int id;
     
    private String content;
     
    // 自動生成get、set方法 
    ...
}

OK,Comment類中有id和content這兩個字段,也就意味着comment表中會有id和content這兩列。

 

接着修改litepal.xml中的配置,在映射列表中新增Cooment類,並將版本號加1,以下所示:

<?xml version="1.0" encoding="utf-8"?>
<litepal>
    <dbname value="demo" ></dbname>
 
    <version value="2" ></version>
 
    <list>
        <mapping class="com.example.databasetest.model.News"></mapping>
        <mapping class="com.example.databasetest.model.Comment"></mapping>
    </list>
</litepal>

沒錯,就是這麼簡單,僅僅兩步,升級的操做就已經完成了,如今咱們只須要操做一下數據庫,comment表就會自動生成了,以下所示:

SQLiteDatabase db = Connector.getDatabase();

那麼咱們仍是經過.table命令來查看一下結果,以下圖所示:

20140914155958796

 

OK,comment表已經出來了,那麼再經過pragma命令來查看一下它的表結構吧:

20140914160140852

 

沒有問題,comment表中目前有id和content這兩列,和Comment模型類中的字段是保持一致的。

那麼如今又來了新的需求,須要在comment表中添加一個publishdate列,該怎麼辦呢?不用懷疑,跟着你的直覺走,相信你已經猜到應該在Comment類中添加這樣一個字段了吧,以下所示:

public class Comment {
     
    private int id;
     
    private String content;
     
    private Date publishDate;
     
    // 自動生成get、set方法 
    ...
}

而後呢?剩下的操做已經很是簡單了,只須要在litepal.xml中對版本號加1就好了,以下所示:

<litepal>
    <dbname value="demo" ></dbname>
 
    <version value="3" ></version>
    ...
</litepal>

這樣當咱們下一次操做數據庫的時候,publishdate列就應該會自動添加到comment表中。調用Connector.getDatabase()方法,而後從新查詢comment表結構,以下所示:

20140914161913495

 

能夠看到,publishdate這一列確實已經成功添加到comment表中了。

經過這兩種升級方式的對比,相信你已經充分體會到了使用LitePal進行升級表操做所帶來的便利了吧。咱們不須要去編寫任何與升級相關的邏輯,也不須要關心程序是從哪一個版本升級過來的,惟一要作的就是肯定好最新的Model結構是什麼樣的,而後將litepal.xml中的版本號加1,全部的升級邏輯就都會自動完成了。LitePal確實將數據庫表的升級操做變得極度簡單,使不少程序員能夠從維護數據庫表升級的困擾中解脫出來。

然而,LitePal卻明顯作到了更好。前面咱們提到過關於刪除列的問題,最終的結論是沒法解決,由於SQLite是不支持刪除列的命令的。可是若是使用LitePal,這一問題就能夠簡單地解決掉,好比說publishdate這一列咱們又不想要了,那麼只須要在Comment類中把它刪除掉,而後將版本號加1,下次操做數據庫的時候這個列就會不見了。

那麼有的朋友可能會問了,不是說SQLite不支持刪除列的命令嗎?那LitePal又是怎樣作到的呢?其實LitePal並無刪除任何一列,它只是先將comment表重命名成一個臨時表,而後根據最新的Comment類的結構生成一個新的comment表,再把臨時表中除了publishdate以外的數據複製到新的表中,最後把臨時表刪掉。所以,看上去的效果好像是作到了刪除列的功能。

這也是使用框架的好處,若是沒有框架的幫助,咱們顯然不會爲了刪除一個列而大廢周章地去寫這麼多的代碼,而使用框架的話,具體的實現邏輯咱們已經不用再關心,只須要控制好模型類的數據結構就能夠了。

另外,若是你想刪除某一張表的話,操做也很簡單,在litepal.xml中的映射列表中將相應的類刪除,表天然也就不存在了。其它的一些升級操做也都是相似的,相信你已經能觸類旁通,這裏就再也不贅述了。

好了,今天對LitePal的介紹就到這裏吧,下篇文章當中咱們會學習使用LitePal來進行表關聯的操做。

相關文章
相關標籤/搜索