FMDB小技巧

FMDB,这个库我也用了很多年了,早些的版本在多线程使用时会报错,不能在不同的线程使用db操作。我自己用单例独立线程出处理这些问题。现在就方便多了,使用GCD,之前介绍GCD说过,fmdb使用一个独立的串行队列,我只要专注于对模型和DAO的编写就足够了。

_queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
dispatch_queue_set_specific(_queue, kDispatchQueueSpecificKey, (__bridge void *)self, NULL);

在使用的地方(inDatabase)做了断言

FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey);
    assert(currentSyncQueue != self && "inDatabase: was called reentrantly on the same queue, which would lead to a deadlock");

使用方式举例

- (WWGroupObject *)selectByGroupId:(NSInteger)groupId
{
__block WWGroupObject *obj = nil;
FMDatabaseQueue *dbQueue = [[WWDatabaseHelper sharedInstance] dbQueue];
[dbQueue inDatabase:^(FMDatabase *db) {
    FMResultSet *rs = [db executeQuery:[self setTable:SELECT_GROUPID_ROSTER], [NSNumber numberWithInteger:groupId]];
    while ([rs next]) {
        obj = [[WWGroupObject alloc] init];
        obj.groupId = [rs intForColumn:@"id"];
        obj.groupName = [rs stringForColumn:@"groupName"];
        obj.groupType = [rs intForColumn:@"groupType"];
        }
    }];
  return obj;
}

因为它是用的dispatch_sync,整个是串行操作,就不会出现不返回数据的情况,之前我还用dispatch_semaphore_t
来判断block是否执行结束然后再返回数据,其实没必要的,串行队列一定是执行完block才return的。

早些版本我是写一个DatabaseHelper单例类保存一个FMDatabase实例,现在是单例类保存一个FMDatabaseQueue实例,它是使用路径初始化的,执行一套sql建表文件executeStatements和更新版本做的一些增删字段的sql语句。

写一堆各种模型,对应数据库表的。

在写一些DAO模块,对应增删改查,DAO使用单例helper的queue执行inDatabase方法,去调用executeQuery执行语句。
这种方式就是看起来比较直观,很容易分模块给别人编写,使用时隐藏了sql,如- (void)insertTitle:(WWTitleObject *)obj,只要初始化这个obj就可以。
安卓下有GreenDao,更方便写模型。

发表评论

电子邮件地址不会被公开。 必填项已用*标注