避免sqlite数据库升级痛苦的小技巧
<p>相信所有使用sqlite做本地缓存的人,开发中不可避免的一件事情就是数据库版本迁移升级,这真的是一件很蛋疼的事情。蛋疼在哪里?</p> <p>1、升级的逻辑,iOS里面你得自己写逻辑,比如记录数据库版本,然后比对啥的。有个基于FMDB 的 FMDBMigrationManager ,不过用起来也不是很顺手。在Android开发中,至少系统SDK还提供了相关的升级API。</p> <p>2、当需要做迁移的时候,也有很多坑,比如说模型:</p> <pre> <code class="language-objectivec">@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") )</code></pre> <p>对应这个模型,数据库里面已经有一张User表了,后面要往User里面增加属性hobby,那么对数据库中已经存在的User表要做如下修改:</p> <pre> <code class="language-objectivec">ALTER TABLE User ADD COLUMN hobby;</code></pre> <p>但是遇到删除属性或者改名字啥的,那就比较蛋疼了,并没有相关的sql语句。你能做的是把数据全读出来,然后建一个新的User表,然后再写进去。</p> <p>如何避免,或者最小化这种痛苦呢?一是在建表的时候把所有情况都考虑进去,后面不再改动model的表结构,这显然不太现实,老版总有改需求的时候。第二种是使用模糊建表方法:所谓模糊建表就是说创建模型表的时候,将数据揉成一坨丢进去,取出来的时候再解析。建表的时候,只取下面几个属性:</p> <p>1、主键,比如上面的userId。</p> <p>2、排序属性,比如上面User要按照年龄排序的话,最好把age属性也存下来。</p> <p>3、数据,所有的内容打包成一个jsonData属性,存起来。</p> <p>那么建表的语句是这样的:</p> <pre> <code class="language-objectivec">// sql建表语句 CREATE TABLE "User" ( "userId" INTEGER NOT NULL, "age" INTEGER, "jsonData" TEXT, PRIMARY KEY("userId") )</code></pre> <p>jsonData从哪里来?很简单,用YYModel之类的模型框架转一遍就够了,下面是代码:</p> <pre> <code class="language-objectivec">// 存数据 [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]; }];</code></pre> <p>这样做的坏处在于,userId和age两个数据在jsonData里面也有一份,有冗余。当然也可以在使用YYModel框架提供的方法在序列化jsonData的时候过滤掉userId和age属性,但是一般没必要这样做,因为冗余数据量很小。好处在于:</p> <p>1、数据库升级迁移的时候,增加一个属性,或者减少一个属性,你只用改模型就好了,存数据和取数据的代码依然可以用。排序属性和主键属性一般没人会改吧?如果你的老板要你改这种基本的属性的话,那么请打死他!</p> <p>2、用YYModel等模型框架来序列化和反序列化减少了存取数据大量繁琐的代码。</p> <p>3、之所以存取主键和排序属性在于这是必须的,主键用来区分,排序属性用来排序,其他的属性统统归为非重要属性,丢到那一坨jsonData里面就可以了。在写创建表的sql语句时,也简化了好多,你只用写很短的几行就行了。当属性比较多的时候,再也不用像这样写了,又臭又长,又容易出错:</p> <pre> <code class="language-objectivec">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") )</code></pre> <p> </p> <p>来自:http://www.jianshu.com/p/21870732fd08</p> <p> </p>
本文由用户 wuwuwuliao 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
转载本站原创文章,请注明出处,并保留原始链接、图片水印。
本站是一个以用户分享为主的开源技术平台,欢迎各类分享!