避免sqlite數據庫升級痛苦的小技巧

wuwuwuliao 7年前發布 | 17K 次閱讀 SQLite

相信所有使用sqlite做本地緩存的人,開發中不可避免的一件事情就是數據庫版本遷移升級,這真的是一件很蛋疼的事情。蛋疼在哪里?

1、升級的邏輯,iOS里面你得自己寫邏輯,比如記錄數據庫版本,然后比對啥的。有個基于FMDB 的 FMDBMigrationManager ,不過用起來也不是很順手。在Android開發中,至少系統SDK還提供了相關的升級API。

2、當需要做遷移的時候,也有很多坑,比如說模型:

@interface User : NSObject

@property (nonatomic, assign) long long userId;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSUInteger *age;

@end

// sql建表語句
CREATE TABLE "User" (
     "userId" INTEGER NOT NULL,
     "name" TEXT,
     "age" INTEGER,
    PRIMARY KEY("userId")
)

對應這個模型,數據庫里面已經有一張User表了,后面要往User里面增加屬性hobby,那么對數據庫中已經存在的User表要做如下修改:

ALTER TABLE User ADD COLUMN hobby;

但是遇到刪除屬性或者改名字啥的,那就比較蛋疼了,并沒有相關的sql語句。你能做的是把數據全讀出來,然后建一個新的User表,然后再寫進去。

如何避免,或者最小化這種痛苦呢?一是在建表的時候把所有情況都考慮進去,后面不再改動model的表結構,這顯然不太現實,老版總有改需求的時候。第二種是使用模糊建表方法:所謂模糊建表就是說創建模型表的時候,將數據揉成一坨丟進去,取出來的時候再解析。建表的時候,只取下面幾個屬性:

1、主鍵,比如上面的userId。

2、排序屬性,比如上面User要按照年齡排序的話,最好把age屬性也存下來。

3、數據,所有的內容打包成一個jsonData屬性,存起來。

那么建表的語句是這樣的:

// sql建表語句
CREATE TABLE "User" (
     "userId" INTEGER NOT NULL,
     "age" INTEGER,
     "jsonData" TEXT,
    PRIMARY KEY("userId")
)

jsonData從哪里來?很簡單,用YYModel之類的模型框架轉一遍就夠了,下面是代碼:

// 存數據
[self.cacheDatabaseQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
        NSString *sql = @"INSERT OR REPLACE INTO User (userId, age, jsonData) VALUES (?, ?, ?);";
        NSNumber *numUserId = [NSNumber numberWithLongLong:user.userId];
        NSNumber *numAge = [NSNumber numberWithUnsignedInteger:user.age];
        NSString *jsonData = [user yy_modelToJSONString];
        success = [db executeUpdate:sql withArgumentsInArray:@[numUserId, numAge, jsonData]];
        if (!success) {
            *rollback = YES;
        }
    }];

// 取數據
    NSMutableArray *array = [NSMutableArray array];
    [self.cacheDatabaseQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = @"SELECT * FROM User ORDER BY age DESC";
        FMResultSet *rsl = [db executeQuery:sql];
        while ([rsl next]) {
            NSString *jsonData = [rsl stringForColumn:@"jsonData"];
            [array addObject:[User yy_modelWithJSON:jsonData]];
        }
        [rsl close];
    }];

這樣做的壞處在于,userId和age兩個數據在jsonData里面也有一份,有冗余。當然也可以在使用YYModel框架提供的方法在序列化jsonData的時候過濾掉userId和age屬性,但是一般沒必要這樣做,因為冗余數據量很小。好處在于:

1、數據庫升級遷移的時候,增加一個屬性,或者減少一個屬性,你只用改模型就好了,存數據和取數據的代碼依然可以用。排序屬性和主鍵屬性一般沒人會改吧?如果你的老板要你改這種基本的屬性的話,那么請打死他!

2、用YYModel等模型框架來序列化和反序列化減少了存取數據大量繁瑣的代碼。

3、之所以存取主鍵和排序屬性在于這是必須的,主鍵用來區分,排序屬性用來排序,其他的屬性統統歸為非重要屬性,丟到那一坨jsonData里面就可以了。在寫創建表的sql語句時,也簡化了好多,你只用寫很短的幾行就行了。當屬性比較多的時候,再也不用像這樣寫了,又臭又長,又容易出錯:

CREATE TABLE "User" (
     "userId" INTEGER NOT NULL,
     "name" TEXT,
     "age" INTEGER,
     "sex" TEXT,
     "languageScores" integer,
     "mathScores" integer,
     "historyScores" integer,
     "class" TEXT,
     "grade" TEXT,
    PRIMARY KEY("userId")
)

 

來自:http://www.jianshu.com/p/21870732fd08

 

 本文由用戶 wuwuwuliao 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!