避免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