iOS Developer首页投稿(暂停使用,暂停投稿)大数据 爬虫Python AI Sql

基于FMDB的数据库基本操作

2017-01-25  本文已影响297人  初心不渝

我们都知道, 不管使用任何一种高级编程语言, 都会遇到需要做本地缓存的情况. 当然, 本地缓存方式可能有多种方式. 但如果需要对本地缓存做灵活的操作, 基于sql 的数据库依然是首选. 本文将从基础的sql语句出发, 衍申到 iOS 开发中对数据库的应用.

一. SQL基础

SQL(结构化查询语言)给我们提供了数据库的创表,删表,数据的增删改查等基本操作. 接下来将依次举例演示这些操作.

二. FMDB中SQL的使用

FMDB 是在iOS开发中常用的第三方数据库操作框架, 其底层实现是对sqlite 的封装. 下文中用到的self.dataBase 是FMDatabase 的单例.

1. FMDatabase 调用 sql 不需要返回数据

FMDatabase 在调用sql 时, 不需要返回数据的情况有 增, 删, 改. 在这种情况下, FMDatabase 提供了两种调用方式.

  NSString *sqlString = [NSString stringWithFormat:@"insert into StudentTable(id,name,score) values ('%@','%@','%@');", @1, @"小明", @99];
       
 BOOL result = [self.dataBase executeUpdate:sqlString];
BOOL result = [self.dataBase executeUpdateWithFormat:@"insert into StudentTable(id,name,score) values (?,?,?)", @1, @"小明", @99];

2. FMDatabase 调用 sql 语句需要返回数据

FMDatabase 在调用sql 时,需要返回数据的操作是 查询. 查询操作也有以上两种调用方式

查询操作返回数据类型是FMResultSet, 需要对这个类型的数据进行解析, 转成模型数据.

- (NSArray *)selectStudentByID:(NSNumber *)ID {
    
    NSMutableArray *resultArray = [NSMutableArray array];
    
    FMResultSet *set = [self.dataBase executeQueryWithFormat:@"select * from StudentTable where id = ?;", ID];
    while (set.next) {
        
        Student *stu = [[Student alloc] init];
        stu.ID = [set objectForColumnName:@"id"];
        stu.name = [set objectForColumnName:@"name"];
        stu.score = [set objectForColumnName:@"score"];
        [resultArray addObject:key];
    }
    return resultArray;
}

三. 异步线程的FMDB

在项目中曾经遇到这么一种情况, 快速切换页面, 大量网络数据需要更新本地数据库的缓存. 操作的特点是: 数据量大, 对数据库的操作频繁, 更有甚者,多个网络数据流同时操作了同一张数据表. 那么这样的操作必然不能放到主线程中执行, 整个app 会卡顿的无法使用, 用户体验相当不好.

这时, 我考虑使用异步线程, 将这些耗时操作放到子线程中去执行. 事实上我也这么尝试了, app 卡顿的现象真的解决了. 在测试过程中, 新的问题又出现了. 问题就是: 多个动作同时操作数据库时, 未必所有动作都会被执行. 因为某张数据表正在被操作, 其他动作则无法操作而被跳过了. 这样, 每次从本地缓存中读取的数据就会和预期的有较大出入.

要解决以上问题, FMDB为我们提供了基于 NSOperationQueue 的多线程操作. 将所有操作放入队列中, iOS系统会自动分配子线程, 确保每个动作都会被执行, 不会因为数据库正在被操作而丢弃其他操作.
下文中用到的self.dataBaseQueue 是FMDatabaseQueue的单例.

- (void)insertStudentsArray:(NSArray *)studentsArray {
    
    [self.dataBaseQueue inDatabase:^(FMDatabase *db) {
        for (Student *stu in studentsArray) {
            [self insertStu: stu];
        }
    }];
}

注意: FMDB提供的队列操作是不能嵌套的, 不能队列中再调用同一队列. 在上面的例子中, -(void)insertStu:(Student*)stu; 这个方法内部就不能再调用[self.dataBaseQueue inDatabase:^(FMDatabase *db) { }]; 这个方法了, 否则程序会崩溃.

上一篇 下一篇

猜你喜欢

热点阅读