FMDB的使用

闲了好久,不知道写点什么,把最近使用FMDB的过程写一下吧!

1. 建立DBManager

建立单例来管理数据库的创建,开启,及增删改查操作。

2. 初始化DataBase,table

使用类属性创建DataBase及DbQueue

@property (nonatomic, class, readonly) FMDatabase *sharedDataBase;
@property (nonatomic, class, readonly) FMDatabaseQueue *dbQueue;

实现方法

+ (FMDatabase *)sharedDataBase {
    static FMDatabase *accountDB = nil;
    @synchronized (self) {
        if (accountDB == nil) {
            NSString *dbPath = [NSHomeDirectory() stringByAppendingFormat:@"/%@",[AccountModel qw_getLocalModel].USERID];
            accountDB = [FMDatabase databaseWithPath:dbPath];
            if ([accountDB open]) {
                DebugLog(@"Database open succeed");
            }else{
                DebugLog(@"Database open failed");
            }
        }
    }
    return accountDB;
}
// 因为FMDB并不是线程安全的,所以建立dbQueue来进行线程操作
static FMDatabaseQueue *_dbQueue = nil;
+ (FMDatabaseQueue *)dbQueue {
    if (_dbQueue == nil) {
        // dbPath和db的path相同,需要先建立数据库,才能够成功创建dbQueue;
        NSString *dbPath = [NSHomeDirectory() stringByAppendingFormat:@"/%@",[AccountModel qw_getLocalModel].USERID];
        _dbQueue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
    }
    return _dbQueue;
}

创建table,根据保存model的类名来创建不同的table

+ (BOOL)createTabelOfClass:(Class)tableClass {
    NSString *excuteStr = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@(id, content)", NSStringFromClass(tableClass)];
    return [[QWDBManager sharedDataBase] executeStatements:excuteStr];
}

3. 建立Catch

建立一个保存model id的数组,用来查询数据库中是否存在该model,减少内存的消耗

@property (nonatomic, strong) NSMutableArray *catchIds;

4. 数据存储,更新

向table中增加model(非线程安全的)

+ (BOOL)addNewModel:(PostModel *)model {
    NSString *addStr = [NSString stringWithFormat:@"INSERT INTO %@ VALUES(?,?)",NSStringFromClass(model.class)];
    BOOL ret = [[QWDBManager sharedDataBase] executeUpdate:addStr, [NSString stringWithFormat:@"%ld", (long)model.PostID], [model qw_dataOfModel]];
    if(ret){
        DebugLog(@"Add model succeed");
    }else{
        DebugLog(@"Add model failed");
    }
    return ret;
}

查询table中是否存在model(非线程安全)第三部分catch的存在就是为了替换掉这个操作,如果有删除model的需要,可以在查询完成后进行删除操作。

+ (BOOL)checkContainModel:(PostModel *)model {
    NSString *checkStr = [NSString stringWithFormat:@"SELECT id FROM %@ WHERE id = ?",NSStringFromClass(model.class)];
    FMResultSet *resultSet = [[QWDBManager sharedDataBase] executeQuery:checkStr, [NSString stringWithFormat:@"%ld",(long)model.PostID]];
    BOOL ret = [resultSet next];
    [resultSet close];
    return ret;
}

更新model内容(非线程安全)

+ (BOOL)updateModel:(PostModel *)model {
    BOOL check = [QWDBManager checkContainModel:model];
    if (check) {
        NSString *updateStr = [NSString stringWithFormat:@"UPDATE %@ SET content = ? WHERE id = %ld",NSStringFromClass(model.class), (long)model.PostID];
        BOOL ret = [[QWDBManager sharedDataBase] executeUpdate:updateStr, [model qw_dataOfModel]];
        ret ? DebugLog(@"Update succeed") : DebugLog(@"Update failed");
        return ret;
    }
    return [QWDBManager addNewModel:model];
}

** 实际项目中model一般都是网络请求到的数据转换而来的,所以涉及到线程操作,而上面这部分操作都不是线程安全的,所以推荐使用下面的这些方法。**

// 更新model的数组
+ (void)async_updateModels:(NSArray *)models {
    [QWDBManager.dbQueue inDatabase:^(FMDatabase *db) {
        [models enumerateObjectsUsingBlock:^(PostModel *obj, NSUInteger idx, BOOL * _Nonnull stop) {
            // 检查catch数组中是否存在model id
            if ([[QWDBManager shareInstance].catchIds containsObject:@(obj.PostID)]) {
                [QWDBManager updateModel:obj inDb:db];
            }else{
                if ([QWDBManager addModels:obj toBb:db]) [[QWDBManager shareInstance].catchIds addObject:@(obj.PostID)]; // 不存在时,将model id 添加到缓存中
            }
            if (stop) {
                // 更新缓存数据
                [[NSUserDefaults standardUserDefaults] setObject:[QWDBManager shareInstance].catchIds forKey:@"CatchModelIdsKey"];
            }
        }];
    }];
}

+ (BOOL)updateModel:(PostModel *)model inDb:(FMDatabase *)db {
    NSString *updateStr = [NSString stringWithFormat:@"UPDATE %@ SET content = ? WHERE id = %ld",NSStringFromClass(model.class), (long)model.PostID];
    BOOL ret = [db executeUpdate:updateStr, [model qw_dataOfModel]];
    if (ret) {
        DebugLog(@"Update model:%ld succeed", (long)model.PostID);
    }else{
        DebugLog(@"Update model:%ld failed", (long)model.PostID);
    }
    return ret;
}

+ (BOOL)addModels:(PostModel *)model toBb:(FMDatabase *)db {
    NSString *addStr = [NSString stringWithFormat:@"INSERT INTO %@ VALUES(?,?)",NSStringFromClass(model.class)];
    BOOL ret = [db executeUpdate:addStr, [NSString stringWithFormat:@"%ld", (long)model.PostID], [model qw_dataOfModel]];
    if (ret) {
        DebugLog(@"Add model:%ld succeed", (long)model.PostID);
    }else{
        DebugLog(@"Add model:%ld failed", (long)model.PostID);
    }
    return ret;
}

恩!大致就这样,最后贴个demo地址:QWPapapa , ** 有问题留言**。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,785评论 18 399
  • SQLite函数总结 1.打开数据库 int sqlite3_open( const char *filename...
    蓝心儿的蓝色之旅阅读 749评论 0 0
  • iOS 中原生的 SQLite API 在使用上相当不友好,在使用时,非常不便。于是,就出现了一系列将SQLite...
    __Mr_Xie__阅读 2,074评论 1 6
  • iOS中原生的SQLite API在使用上相当不友好,在使用时,非常不便。于是,就出现了一系列将SQLite AP...
    南衍儿阅读 2,079评论 0 0
  • 好几年不联系的大学同学,昨天突然建了一个微信群,聊得热火朝天,仿佛回到了读书时代。虽然见不到面,依旧能从熟悉声音语...
    123wansui阅读 598评论 0 0