文章目录
  1. 1. 前言
  2. 2. 安装
  3. 3. 使用
  4. 4. 创建数据库
  5. 5. 打开数据库
    1. 5.1. 执行更新
  6. 6. 执行查询
  7. 7. 关闭数据库
  8. 8. 事务
  9. 9. 使用线程安全的FMDatabaseQueue
  10. 10. 参考

前言

FMDB 是一款使用Objective-C对SQLite进行封装的优秀的第三方框架,加上了面向对象的思想。

优点:

  • 使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码
  • 对比苹果自带的CoreData框架,更加轻量级和灵活
  • 提供多线程安全,有效地防止数据混乱,原来的SQLite不是线程安全的
  • 支持使用Swift调用

缺点:

  • 因为是OC语言封装的,失去了SQLite原来的跨平台性

FMDB的方方面面在Github上已经交代的比较明白,这里自己再总结摘要一下。

安装

  • 在Github上下载FMBDB源码,将文件拖入工程
  • 在项目target的Build Phases->Link Bianry With Libraries中添加libsqlite3.tbd依赖库
  • #import “FMDatabase.h”

    使用

    主要包含如下三个类:
  • FMDatabase - 代表一个SQLite数据库,用来在单一线程中执行SQL语句,线程不安全。
  • FMResultSet - 代表执行一次查询后的结果。
  • FMDatabaseQueue - 用于多线程操作数据库的查询和更新,线程安全。

创建数据库

支持传入3种文件路径:

  • 传入真实的文件系统路径,如不存在该文件,将自动创建;
  • 传入空字符串@””. 创建一个本地的临时数据库,当FMDatabase连接关掉后将被自动删除;
  • 传入NULL.创建一个in-memory数据库,当FMDatabase连接关掉后将被自动释放。
1
2
3
4
NSArray* array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documents = [array objectAtIndex:0];
NSString* path = [documents stringByAppendingPathComponent:@"test.db"];
FMDatabase* db = [FMDatabase databaseWithPath:path];

打开数据库

在使用之前,必须先调用open函数,保证数据库被打开。当资源不足或权限不够时,可能会open失败,这时需要返回,无法后续操作。

1
2
3
4
if (![db open]) {
db = nil;
return;
}

执行更新

任何不以SELECT开头的SQL操作都属于更新操作,包括 CREATE, UPDATE, INSERT, ALTER, COMMIT, BEGIN, DETACH, DELETE, DROP, END, EXPLAIN, VACUUM, 以及 REPLACE 等,通过-executeUpate...这种方法来执行,执行更新正确会返回YES,否则返回NO。

1
2
3
BOOL updateResult = [db executeUpdate:@"CREATE TABLE myTable (num integer, name varchar(7), sex char(1), primary key(num))"];
if (!updateResult) {return;}
updateResult = [db executeUpdate:@"INSERT INTO myTable(num, name, sex) values(?,?,?)", @0, @"hha", @"m"];

执行查询

一个SELECT查询语句将通过-executeQuery...这种方法来执行,如果正确,返回一个FMResultSet对象,否则返回nil。必须使用-lastErrorMessage和-lastErrorCode方法来查询为何执行失败。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
FMResultSet* result = [db executeQuery:@"SELECT * FROM myTable"];
NSMutableArray *array = [NSMutableArray array];
while ([result next]) {
//根据字段名,获取记录的值,存储到字典中
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
int num = [result intForColumn:@"num"];
NSString *name = [result stringForColumn:@"name"];
NSString *sex = [result stringForColumn:@"sex"];
dict[@"num"] = @(num);
dict[@"name"] = name;
dict[@"sex"] = sex;
//把字典添加进数组中
[array addObject:dict];
}

关闭数据库

调用close方法即可。

事务

事务,是指作为单个逻辑工作单元执行的一系列操作,要么完整地执行,要么完全地不执行。
想象一个场景,比如你要更新数据库的大量数据,我们需要确保所有的数据更新成功,才采取这种更新方案,如果在更新期间出现错误,就不能采取这种更新方案了,如果我们不使用事务,我们的更新操作直接对每个记录生效,万一遇到更新错误,已经更新的数据怎么办?难道我们要一个一个去找出来修改回来吗?怎么知道原来的数据是怎么样的呢?这个时候就需要使用事务实现。

SQLite进行事务处理:

  • 只要在执行SQL语句前加上以下的SQL语句,就可以使用事务功能了:
  • 开启事务的SQL语句,”begin transaction;”
  • 进行提交的SQL语句,”commit transaction;”
  • 进行回滚的SQL语句,”rollback transaction;”

FMDatabase使用事务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//事务
-(void)transaction {
// 开启事务
[self.database beginTransaction];
BOOL isRollBack = NO;
@try {
for (int i = 0; i<500; i++) {
NSNumber *num = @(i+1);
NSString *name = [[NSString alloc] initWithFormat:@"student_%d",i];
NSString *sex = (i%2==0)?@"f":@"m";
NSString *sql = @"insert into mytable(num,name,sex) values(?,?,?);";
BOOL result = [database executeUpdate:sql,num,name,sex];
if ( !result ) {
NSLog(@"插入失败!");
return;
}
}
}
@catch (NSException *exception) {
isRollBack = YES;
// 事务回退
[self.database rollback];
}
@finally {
if (!isRollBack) {
//事务提交
[self.database commit];
}
}
}

使用线程安全的FMDatabaseQueue

不能在线程间共用一个FMDatabase, 否则会造成数据混乱! 如果需要使用多线程,应该使用线程安全的FMDatabaseQueue. (#import “FMDatabaseQueue.h” 即可)
FMDatabaseQueue的操作与FMDatabase非常类似,如

  • 创建
    FMDatabaseQueue* queue = [FMDatabaseQueue databaseQueueWithPath: aPath];
  • 操作

    将FMDatabase中的操作放到

    1
    2
    3
    [queue inDatabase:^(FMdatabase*db){
    //FMDatabase操作
    }];

即可。

1
2
3
4
5
6
7
8
9
[queue inDatabase:^(FMDatabase*db) {
//插入记录到表中
NSString *sqlStr = @"insert into mytable(num,name,sex) values(4,'xiaoming','m');";
BOOL result = [db executeUpdate:sqlStr];
if (!result) {
NSLog(@"error when insert into database table");
[db close];
}
}];
  • 事务

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //多线程事务
    - (void)transactionByQueue {
    //开启事务
    [self.queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
    for (int i = 0; i<500; i++) {
    NSNumber *num = @(i+1);
    NSString *name = [[NSString alloc] initWithFormat:@"student_%d",i];
    NSString *sex = (i%2==0)?@"f":@"m";
    NSString *sql = @"insert into mytable(num,name,sex) values(?,?,?);";
    BOOL result = [db executeUpdate:sql,num,name,sex];
    if ( !result ) {
    //当最后*rollback的值为YES的时候,事务回退,如果最后*rollback为NO,事务提交
    *rollback = YES;
    return;
    }
    }
    }];
    }

参考

iOS学习笔记17-FMDB你好!

文章目录
  1. 1. 前言
  2. 2. 安装
  3. 3. 使用
  4. 4. 创建数据库
  5. 5. 打开数据库
    1. 5.1. 执行更新
  6. 6. 执行查询
  7. 7. 关闭数据库
  8. 8. 事务
  9. 9. 使用线程安全的FMDatabaseQueue
  10. 10. 参考