FMDB简介
iOS中原生的SQLite API在进行数据存储的时候,需要使用C语言中的函数,操作比较频繁。于是,就出现了一系列将AQLite API进行封装的库,例如FMDB、PlausibleDatabase、SQLitePersistenrObjects等
FMDB是一款简洁,简易的封装库。因此在这里推荐使用第三方框架FMDB,它是对理不清lite框架的封装,用起来的步骤和SQLite使用类似,并且它对于多线程的并发操作进行了处理,所以是线程安全的
FMDB优缺点
优点:
1.对多线程的并发操作进行处理,所以是线程安全的
2.以OC的方式封装了SQLite的C语言API,使用起来更加的方便
3.FMDB是轻量级的框架,使用灵活
缺点:
1.因为它是OC的语言封装的,只能在iOS开发的时候使用,所以在实现跨平台操作的时候存在局限性
FMDB中的重要类
- FMDaraBase:一个FMDaraBase对象就代表一个单独的SQLite数据库,用来执行SQL语句
- FMRresultSet:使用FMDaraBase执行查询后的结果集
- FMDatabaseQueue:用于在多线程中执行多个查询或更新,它是线程安全的
FMDB使用步骤
1.下载FMDB文件(可以将FMDB文件夹添加到项目中,也可以使用CocoaPods导入)
2.导入libsqlite3.0框架,导入头文件FMDatabase.h
3.代码实现,与SQLite使用步骤相似,创建数据库路径,获得数据库路径,打开数据库,然后对数据库进行增删改查操作,最后关闭数据库
第一步引入框架 , 引入支持的类库
1 #import "ViewController.h" 2 // 第一步引入框架 , 引入支持的类库 3 #import <FMDB.h> 4 // libsqlite3.0.tbd 5 6 @interface ViewController () 7 /// 声明数据库对象 8 @property (nonatomic,strong) FMDatabase *dataBase; 9 /// 声明存储路径 10 @property (nonatomic,copy) NSString *filePath; 11 12 @end
创建表和数据库
1 #pragma mark - 创建表 2 - (void)createTable { 3 // 第一步:创建sql语句 4 NSString *createSqlite = @"create table if not exists t_student(id integer primary key autoincrement not null, name text not null, age integer not null, sex text not null)"; 5 // 第二步:找到文件夹路径 6 NSString *document = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 7 NSLog(@"document:%@",document); 8 // 拼接 9 self.filePath = [document stringByAppendingPathComponent:@"student.sqlite"]; 10 NSLog(@"filePath:%@",self.filePath); 11 // 第三步:初始化FMDB 12 self.dataBase = [FMDatabase databaseWithPath:self.filePath]; 13 // 第四步:数据库执行相关的操作 14 // 需要判断数据库打开的时候才进行执行语句 15 if ([self.dataBase open]) { 16 BOOL result = [self.dataBase executeUpdate:createSqlite]; 17 if (result) { 18 NSLog(@"建表成功"); 19 } else { 20 NSLog(@"建表失败"); 21 } 22 } 23 // 第五步:关闭数据库 24 [self.dataBase close]; 25 }
第一种:添加的方法
1 #pragma mark - 增加 2 - (IBAction)addAction:(id)sender { 3 // 第一步:打开数据库 4 [self.dataBase open]; 5 // 第二步:进行相关的操作 6 NSArray *nameArray = [NSArray arrayWithObjects:@"mbboy", @"zhatian", @"小明", nil]; 7 for (int i = 0; i < nameArray.count; i++) { 8 NSString *name = [nameArray objectAtIndex:i]; 9 // 插入语句 10 NSString *insertSql = @"insert into t_student(name,age,sex) values(?,?,?)"; 11 BOOL result = [self.dataBase executeUpdate:insertSql, name, @69, @"m"]; 12 if (result) { 13 NSLog(@"添加成功"); 14 } else { 15 NSLog(@"添加失败"); 16 } 17 } 18 [self.dataBase close]; 19 }
第二种:以列队的形式添加
1 #pragma mark - 以队列的形式添加 2 // 以队列的形式添加数据FMDB比较常用的添加方式 3 // FMDB不支持多个线程同时操作,所以一般以串行的方式实现相关操作 4 - (IBAction)insertManyStudent:(id)sender { 5 // 第一步:打开数据库 6 [self.dataBase open]; 7 // 第二步:创建操作队列 8 FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:self.filePath]; 9 // 标识:记录是否操作成功 10 __block BOOL isSucceed = YES; 11 // 第三步:把所需要的事情打包放在队列中 12 [queue inTransaction:^(FMDatabase *db, BOOL *rollback) { 13 // 串行队列 14 isSucceed = [db executeUpdate:@"insert into t_student(name,age,sex) values(?,?,?)", @"gblw", @38, @"nan"] && isSucceed; 15 isSucceed = [db executeUpdate:@"insert into t_student(name,age,sex) values(?,?,?)", @"black", @22, @"nv"] && isSucceed; 16 isSucceed = [db executeUpdate:@"insert into t_student(name,age,sex) values(?,?,?)", @"-1", @69, @"nan"] && isSucceed; 17 // 如果有错误,就会将它返回 18 if (!isSucceed) { 19 // block返回的参数 rollback进行处理 (bool类型的指针) 20 *rollback = YES; 21 return ; 22 }
23 // 这句代码,假设在执行第一句执行完后,数据库服务器故障,抛出异常了,第二句就没有执行。这时候数据库的情况就是:id为1的name更新了,id为2的name没有更新。假设业务逻辑不能容忍这种只执行一半的情况,那么就应该rollback,把id为1的name恢复到一切执行之前的情况。 24 // 如果业务逻辑可以容忍这种只执行一半SQL的行为,那就不需要rollback。 25 // 数据库事务控制的精髓就一句话:对于一堆sql语句来说,要么都执行,要么都不执行。其中“要么都不执行”的部分,就是用rollback实现的 26 }]; 27 [self.dataBase close]; 28 }
注:rollback 回滚的意思。 就是数据库里做修改后( update ,insert , delete)未 commit 之前 使用 rollback 可以恢复数据到修改之前。
删除、修改
1 #pragma mark - 删除 2 - (IBAction)deleteAction:(id)sender { 3 // 第一步:打开数据库 4 [self.dataBase open]; 5 // 第二步:执行相关操作 6 BOOL result = [self.dataBase executeUpdate:@"delete from t_student where name = ?", @"zhatian"]; 7 if (result) { 8 NSLog(@"删除成功"); 9 } else { 10 NSLog(@"删除失败"); 11 } 12 [self.dataBase class]; 13 } 14 #pragma mark - 修改 15 - (IBAction)updateAction:(id)sender { 16 // 第一步:打开数据库 17 [self.dataBase open]; 18 // 第二步:进行相关操作 19 BOOL result = [self.dataBase executeUpdate:@"update t_student set name = ? where name = ?", @"孟玲旭", @"mbboy"]; 20 21 if (result) { 22 NSLog(@"修改成功"); 23 } else { 24 NSLog(@"修改失败"); 25 } 26 [self.dataBase close]; 27 }
SELECT命令就是查询,执行查询的类 FMResultSet 方法是 executeQuery
1 #pragma mark - 查询表中的所有数据 2 - (IBAction)searchAction:(id)sender { 3 // 第一步:打开数据库 4 [self.dataBase open]; 5 // 第二步:进行相关操作 6 // 查询结果使用的类FMResultSet 7 FMResultSet *resultSet = [self.dataBase executeQuery:@"select * from t_student"]; 8 // 遍历出需要的结果内容 9 while ([resultSet next]) { 10 NSInteger idNum = [resultSet intForColumn:@"id"]; 11 NSString *name = [resultSet objectForColumnName:@"name"]; 12 NSInteger age = [resultSet intForColumn:@"age"]; 13 NSString *sex = [resultSet objectForColumnName:@"sex"]; 14 NSLog(@"id:%ld, name:%@, age:%ld, sex:%@", idNum, name, age, sex); 15 } 16 [self.dataBase close]; 17 } 18 19 - (void)didReceiveMemoryWarning { 20 [super didReceiveMemoryWarning]; 21 // Dispose of any resources that can be recreated. 22 }