iOS下FMDB的多线程操作(一)
来源:互联网 发布:水冷机箱推荐 知乎 编辑:程序博客网 时间:2024/05/29 10:36
iOS中一些时间比较长的操作都应该放在子线程中,以避免UI的卡顿。而sqlite 是非线程安全的,故在多线程中不能共用同一个数据库连接,否则会导致EXC_BAD_ACCESS。所以我们可以在子线程中创建一个新的db连接(新建一个db对象),然后再操作数据库。
如果选择FMDB,除了以上所说的方式外,还可以利用FMDatabaseQueue来解决多线程问题。
关于FMDB的使用网上教程比较多,内容基本都是与唐巧的这篇http://www.devtang.com/blog/2012/04/22/use-fmdb/差不多
这里记录一下多线程下的使用。
方式一:采用每次新建db的方式
db路径我是写了一个方法
+ (NSString *)getDBPath{ NSString* docsdir = [NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; NSFileManager *filemanage = [NSFileManager defaultManager]; docsdir = [docsdir stringByAppendingPathComponent:@"FMDBDemo"]; BOOL isDir; BOOL exit =[filemanage fileExistsAtPath:docsdir isDirectory:&isDir]; if (!exit || !isDir) { [filemanage createDirectoryAtPath:docsdir withIntermediateDirectories:YES attributes:nil error:nil]; } NSString *dbpath = [docsdir stringByAppendingPathComponent:@"myDB.sqlite"]; return dbpath;}
1、创建数据库表
/** 创建表 */+ (BOOL)createUserTableByDB{ FMDatabase *db = [FMDatabase databaseWithPath:[self getDBPath]]; if (![db open]) { NSLog(@"数据库打开失败!"); return NO; } NSString *sql = @"CREATE TABLE IF NOT EXISTS User(ID INTEGER PRIMARY KEY, name TEXT, age INTEGER, ID_No TEXT);"; BOOL res = [db executeUpdate:sql]; if (res) { NSLog(@"创建表格成功"); }else { NSLog(@"创建表格失败"); } return res;}2、插入数据
插入数据,我分了两种情形,一种是单条插入,一种是利用事务(利用事务插入多条时,时间会快很多,而且有任何一条插入失败,则不会提交到数据库)
/** 保存单个对象 */- (BOOL)saveByDB{ FMDatabase *db = [FMDatabase databaseWithPath:[User getDBPath]]; if (![db open]) { NSLog(@"数据库打开失败!"); return NO; } NSString *sql = [NSString stringWithFormat:@"INSERT INTO User(name, age, ID_No) VALUES ('%@', '%d', '%@');", self.name, self.age, self.ID_no]; BOOL res = [db executeUpdate:sql]; [db close]; if (res) { NSLog(@"插入数据成功"); }else { NSLog(@"插入数据失败"); } return res;}/** 批量保存用户对象 */+ (BOOL)saveObjectsByDB:(NSArray *)array{ FMDatabase *db = [FMDatabase databaseWithPath:[self getDBPath]]; if (![db open]) { NSLog(@"数据库打开失败!"); return NO; } [db beginTransaction]; BOOL isRollBack = NO; @try { for (User *user in array) { NSString *sql = [NSString stringWithFormat:@"INSERT INTO User(name, age, ID_No) VALUES ('%@', '%d', '%@');", user.name, user.age, user.ID_no]; BOOL res = [db executeUpdate:sql]; if (!res) { NSLog(@"db事务插入失败"); }else { NSLog(@"db事务插入成功"); } } } @catch (NSException *exception) { isRollBack = YES; [db rollback]; } @finally { if (!isRollBack) { [db commit]; } } [db close]; return !isRollBack;}
更新与删除也分两种情形,与插入类似。
3、更新数据
/** 更新单个对象 */- (BOOL)updateByDB{ FMDatabase *db = [FMDatabase databaseWithPath:[User getDBPath]]; if (![db open]) { NSLog(@"数据库打开失败!"); return NO; } NSString *sql = [NSString stringWithFormat:@"UPDATE User SET name = '%@',age = '%d',ID_no = '%@' WHERE ID = '%d';", self.name, self.age, self.ID_no, self.ID]; BOOL res = [db executeUpdate:sql]; [db close]; if (res) { NSLog(@"插入数据成功"); }else { NSLog(@"插入数据失败"); } return res;}/** 批量更新用户对象*/+ (BOOL)updateObjectsByDB:(NSArray *)array{ FMDatabase *db = [FMDatabase databaseWithPath:[User getDBPath]]; if (![db open]) { NSLog(@"数据库打开失败!"); return NO; } [db beginTransaction]; BOOL isRollBack = NO; @try { for (User *user in array) { NSString *sql = [NSString stringWithFormat:@"UPDATE User SET name = '%@',age = '%d',ID_no = '%@' WHERE ID = '%d';", user.name, user.age, user.ID_no, user.ID]; BOOL res = [db executeUpdate:sql]; if (!res) { NSLog(@"db事务更新失败"); }else { NSLog(@"db事务更新成功"); } } } @catch (NSException *exception) { isRollBack = YES; [db rollback]; } @finally { if (!isRollBack) { [db commit]; } } [db close]; return !isRollBack;}4、删除数据
/** 删除单个对象 */- (BOOL)deleteObjectByDB{ FMDatabase *db = [FMDatabase databaseWithPath:[User getDBPath]]; if (![db open]) { NSLog(@"数据库打开失败!"); return NO; } NSString *sql = [NSString stringWithFormat:@"DELETE FROM User WHERE ID = '%d'",self.ID]; BOOL res = [db executeUpdate:sql]; [db close]; if (res) { NSLog(@"删除数据成功"); }else { NSLog(@"删除数据失败"); } return res;}/** 批量删除用户对象 */+ (BOOL)deleteObjectsByDB:(NSArray *)array{ FMDatabase *db = [FMDatabase databaseWithPath:[self getDBPath]]; if (![db open]) { NSLog(@"数据库打开失败!"); return NO; } [db beginTransaction]; BOOL isRollBack = NO; @try { for (User *user in array) { NSString *sql = [NSString stringWithFormat:@"DELETE FROM User WHERE ID = '%d'",user.ID]; BOOL res = [db executeUpdate:sql]; if (!res) { NSLog(@"db事务删除失败"); }else { NSLog(@"db事务删除成功"); } } } @catch (NSException *exception) { isRollBack = YES; [db rollback]; } @finally { if (!isRollBack) { [db commit]; } } [db close]; return !isRollBack;}
5、查询数据
查询就比较简单了。
/** 查询全部用户 */+ (NSArray *)findAllByDB{ FMDatabase *db = [FMDatabase databaseWithPath:[self getDBPath]]; if (![db open]) { NSLog(@"数据库打开失败!"); return nil; } NSMutableArray *users = [[NSMutableArray alloc] init]; NSString *sql = @"SELECT * FROM User"; FMResultSet *resultSet = [db executeQuery:sql]; while ([resultSet next]) { User *user = [[User alloc] init]; user.ID = [resultSet intForColumn:@"ID"]; user.name = [resultSet stringForColumn:@"name"]; user.age = [resultSet intForColumn:@"age"]; user.ID_no = [resultSet stringForColumn:@"ID_no"]; [users addObject:user]; [user release]; } NSLog(@"查询全部成功"); return [users autorelease];}/** 查找某个用户 */+ (instancetype)findFirstBySqlByDB:(NSString *)sql{ User *user = nil; NSArray *users = [self findBySqlByDB:sql]; if (users.count > 0) { user = [users firstObject]; } return user;}/** 查找用户 */+ (NSArray *)findBySqlByDB:(NSString *)sql{ FMDatabase *db = [FMDatabase databaseWithPath:[self getDBPath]]; if (![db open]) { NSLog(@"数据库打开失败!"); return nil; } NSMutableArray *users = [[NSMutableArray alloc] init]; NSString *select = @"SELECT * FROM User "; if (sql) { select = [select stringByAppendingString:sql]; } FMResultSet *resultSet = [db executeQuery:select]; while ([resultSet next]) { User *user = [[User alloc] init]; user.ID = [resultSet intForColumn:@"ID"]; user.name = [resultSet stringForColumn:@"name"]; user.age = [resultSet intForColumn:@"age"]; user.ID_no = [resultSet stringForColumn:@"ID_no"]; [users addObject:user]; [user release]; } NSLog(@"条件查询成功"); return [users autorelease];}
而多线程下的调用方式是这样的,其中上面的所有方法都是在对象类User中。
/** 用db插入User数据*/- (IBAction)dbInsertData:(id)sender { //多线程插入数据 for (int i = 0; i < 5; i++) { dispatch_async(dispatch_get_global_queue(0, 0), ^{ User *user = [[User alloc] init]; user.name = @"dbName一"; user.ID_no = [NSString stringWithFormat:@"%d",55555+i]; user.age = 555+i; [user saveByDB]; }); } //利用事务插入数据 dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSMutableArray *array = [NSMutableArray array]; for (int i = 0; i < 5; i++) { User *user = [[User alloc] init]; user.name = @"db事务"; user.ID_no = [NSString stringWithFormat:@"%d",66666+i]; user.age = 66+i; [array addObject:user]; [user release]; } [User saveObjectsByDB:array]; });}
0 0
- iOS下FMDB的多线程操作(一)
- iOS下FMDB的多线程操作(二)
- iOS 使用FMDB进行数据库操作(一)
- IOS 操作数据库(FMDB)
- ios-FMDB多线程的使用技巧
- iOS关于数据库的操作(使用第三方类库FMDB)
- iOS关于数据库的操作(使用第三方类库FMDB)
- iOS的数据库相关操作(基于fmdb)
- iOS FMDB的一些基本操作小结
- iOS FMDB的操作使用原理
- iOS 基于FMDB简单的查询操作
- 【iOS】数据库FMDB的使用(一)
- FMDB(数据库的操作)
- 数据库操作(fmdb多线程操作)
- FMDB下的数据库操作DML语言
- IOS FMDB操作SQLite3
- iOS下 FMDB 简单的代码例子
- FMDB 的使用(二)多线程问题
- Disruptor 极速体验
- Hibernate 事务处理和spring中配置事务
- java初始化顺序super
- 收藏的iOS技术网站汇总(持续更新ing)
- Java序列划分问题算法实现
- iOS下FMDB的多线程操作(一)
- JS-prototype(实例说明)
- Android设置界面实现
- UIImage与NSString(OC)或者 String (Swift)使用base64的转换
- 网络知识点总结(一)
- tomcat性能优化参数
- 大型商贸系统(进货管理)技术解析(三)自营进仓冲红单
- 概述FaceRecognizer人脸识别类contrib
- 让代码中的属性可以在storyboard的右边栏中进行设置