#import "ViewController.h"
#import "FMDB.h"
@interface ViewController ()
@property (nonatomic, strong) FMDatabaseQueue *queue;
@implementation ViewController
/**
FMDB的细节
1. 数据库是什么时候打开的?
在实例化queue时就打开了
2. FMDB操作多线程是如何实现的?
是使用GCD的串行对列来实现多线程处理的
3. FMDB的数据库操作,FMDatabaseQueue默认是在主线程上
4. FMDB的多线程操作方式:
串行队列 - 保证队列中的任务按照顺序派发,调度
同步任务 - 不会开启线程,任务顺序执行
FMDB本质上可以允许在后台线程执行数据操作,但是要求所有的数据操作,必须顺序执行!
多线程:串行队列,异步任务,开启一条线程,所有任务顺序执行!
如果也要让FMDB具有多线程功能,需要自己开启一个并发队列,让所有数据操作由并发队列调度
5. 一定注意:在使用FMDB时,一定不要嵌套任务使用,否则会死锁!本质上是为了保证数据安全!
*/
- (FMDatabaseQueue *)queue {
if (_queue == nil) {
NSString *dbPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
dbPath = [dbPath stringByAppendingPathComponent:@"my.db"];
// 在指定数据库路径的同时,如果数据库不存在,会自动创建并且打开
_queue = [[FMDatabaseQueue alloc] initWithPath:dbPath];
}
return _queue;
}
- (void)viewDidLoad {
[super viewDidLoad];
// 要把数据库操作,放在后台线程执行
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self createTables];
[self insertRecord];
});
NSLog(@"%@", NSHomeDirectory());
}
/** 创建表 */
- (void)createTables {
// 在事务中执行SQL,
[self.queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
// db 直接执行sql
BOOL result = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS T_Company ("
"companyId integer PRIMARY KEY AUTOINCREMENT NOT NULL,"
"companyName text"
");"];
if (result) {
NSLog(@"创表成功! %@", [NSThread currentThread]);
}
// 插入数据
// 注意:如果再次调用数据操作方法,会造成死锁(在这里使用,会嵌套起来,串行队列,异步任务,所有任务顺序执行,如果嵌套起来会发生死锁)
// [self insertRecord];
}];
}
- (void)insertRecord {
[self.queue inDatabase:^(FMDatabase *db) {
// 插入公司数据
[db executeUpdate:@"insert into t_company (companyName) values ('qq')"];
NSLog(@"插入成功 %@", [NSThread currentThread]);
}];
}
@end