FMDB使用札记

From: http://vin-zhou.github.io/2016/11/18/FMDB%E4%BD%BF%E7%94%A8%E6%9C%AD%E8%AE%B0/

文章目录

    1. 前言
    1. 安装
    1. 使用
    1. 创建数据库
    1. 打开数据库
    2. 5.1. 执行更新
    1. 执行查询
    1. 关闭数据库
    1. 事务
    1. 使用线程安全的FMDatabaseQueue
    1. 参考

前言

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

[1]:

优点:

  • 使用起来更加面向对象,省去了很多麻烦、冗余的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
5
6
7
8
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
5
6
7
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
4
5
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
15
16
17
18
19
20
21
22
23
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
-(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
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
[queue inDatabase:^(FMdatabase*db){
}];
即可。
[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];
}
}];
* 事务
- (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;
return;
}
}
}];
}

参考

iOS学习笔记17-FMDB你好!

Author

陈昭

Posted on

2017-11-09

Updated on

2021-12-27

Licensed under

You need to set install_url to use ShareThis. Please set it in _config.yml.
You forgot to set the business or currency_code for Paypal. Please set it in _config.yml.

Kommentare

You forgot to set the shortname for Disqus. Please set it in _config.yml.