为了多线程操作数据库安全,FMDB使用了FMDatabaseQueue,使用FMDatabaseQueue很简单,首先用一个数据库文件地址来初使化FMDatabaseQueue,然后就可以将一个闭包(block)传入inDatabase方法中。 在闭包中操作数据库,而不直接参与FMDatabase的管理。
NSString *filePath=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"fmdb.sqlite"];
//创建数据库
self.db=[FMDatabase databaseWithPath:filePath];
//打开数据库
if ([self.db open]) {
NSLog(@"打开数据库成功");
//创建表格,除了select外,所有的操作都是更新
BOOL createTableResult=[self.db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_student (id integer PRIMARY KEY AUTOINCREMENT,name text,age integer)"];
if (createTableResult) {
NSLog(@"创建表成功");
}else{
NSLog(@"创建表失败");
}
}else{
NSLog(@"打开数据库失败");
}
}
- (IBAction)insert:(id)sender {
for (int index=0; index<50; index++) {
NSString *s_name=[NSString stringWithFormat:@"Andy%d",arc4random()%100];
NSNumber *s_age=@(arc4random()%100);
[self.db executeUpdate:@"INSERT INTO t_student(name,age) VALUES(?,?)",s_name,s_age];
}
}
- (IBAction)delete:(id)sender {
[self.db executeUpdate:@"DELETE FROM t_student WHERE id=?",@1];
}
- (IBAction)update:(id)sender {
[self.db executeUpdate:@"UPDATE t_student SET name='Jack' WHERE id=?",@2];
}
- (IBAction)select:(id)sender {
//获取结果集,返回参数就是查询结果
FMResultSet *rs=[self.db executeQuery:@"SELECT * FROM t_student WHERE age>?",@50];
while ([rs next]) {
int ID=[rs intForColumn:@"id"];
NSString *NAME=[rs stringForColumn:@"name"];
int AGE=[rs intForColumn:@"age"];
NSLog(@"%d %@ %d",ID,NAME,AGE);
}
使用FMDatabaseQueue保证线程安全
NSString *filePath=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"fmdb.sqlite"];
//创建数据库,并加入到队列中,此时已经默认打开了数据库,无须手动打开,只需要从队列中去除数据库即可
self.queue=[FMDatabaseQueue databaseQueueWithPath:filePath];
//取出数据库,这里的db就是数据库,在数据库中创建表
[self.queue inDatabase:^(FMDatabase *db) {
//创建表
BOOL createTableResult=[db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_student (id integer PRIMARY KEY AUTOINCREMENT,name text,age integer)"];
if (createTableResult) {
NSLog(@"创建表成功");
}else{
NSLog(@"创建表失败");
}
}];
}
- (IBAction)insert:(id)sender {
[self.queue inDatabase:^(FMDatabase *db) {
for (int index=0; index<50; index++) {
NSString *s_name=[NSString stringWithFormat:@"Andy%d",arc4random()%100];
NSNumber *s_age=@(arc4random()%100);
[db executeUpdate:@"INSERT INTO t_student(name,age) VALUES(?,?)",s_name,s_age];
}
}];
}
- (IBAction)delete:(id)sender {
[self.queue inDatabase:^(FMDatabase *db) {
[db executeUpdate:@"DELETE FROM t_student WHERE id=?",@1];
}];
}
- (IBAction)update:(id)sender {
[self.queue inDatabase:^(FMDatabase *db) {
[db executeUpdate:@"UPDATE t_student SET name='Jack' WHERE id=?",@2];
}];
}
- (IBAction)select:(id)sender {
[self.queue inDatabase:^(FMDatabase *db) {
//获取结果集,返回参数就是查询结果
FMResultSet *rs=[db executeQuery:@"SELECT * FROM t_student WHERE age>?",@50];
while ([rs next]) {
int ID=[rs intForColumn:@"id"];
NSString *NAME=[rs stringForColumn:@"name"];
int AGE=[rs intForColumn:@"age"];
NSLog(@"%d %@ %d",ID,NAME,AGE);
}
}];}
批处理回滚
__block BOOL result = YES;
[self.fmdbQueue inTransaction:^(FMDatabase db, BOOLrollback) {
NSDate *date = [NSDate date];
long long time = (long long)[date timeIntervalSince1970];
NSString *querySql = [NSString stringWithFormat:SQL_INSERT_FRIEND,aFriend.nubeNumber, aFriend.name, time];
LogWriterD(@"保存好友:%@",querySql);
result = result && [db executeUpdate:querySql];
if (!result) {
LogWriterE(@"保存好友失败,回滚保存操作");
*rollback = YES;
}}];