為了多線程操作數(shù)據(jù)庫安全,F(xiàn)MDB使用了FMDatabaseQueue,使用FMDatabaseQueue很簡單,首先用一個數(shù)據(jù)庫文件地址來初使化FMDatabaseQueue,然后就可以將一個閉包(block)傳入inDatabase方法中。 在閉包中操作數(shù)據(jù)庫,而不直接參與FMDatabase的管理。
NSString *filePath=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"fmdb.sqlite"];
//創(chuàng)建數(shù)據(jù)庫
self.db=[FMDatabase databaseWithPath:filePath];
//打開數(shù)據(jù)庫
if ([self.db open]) {
NSLog(@"打開數(shù)據(jù)庫成功");
//創(chuàng)建表格,除了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(@"創(chuàng)建表成功");
}else{
NSLog(@"創(chuàng)建表失敗");
}
}else{
NSLog(@"打開數(shù)據(jù)庫失敗");
}
}
- (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 {
//獲取結(jié)果集,返回參數(shù)就是查詢結(jié)果
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"];
//創(chuàng)建數(shù)據(jù)庫,并加入到隊(duì)列中,此時已經(jīng)默認(rèn)打開了數(shù)據(jù)庫,無須手動打開,只需要從隊(duì)列中去除數(shù)據(jù)庫即可
self.queue=[FMDatabaseQueue databaseQueueWithPath:filePath];
//取出數(shù)據(jù)庫,這里的db就是數(shù)據(jù)庫,在數(shù)據(jù)庫中創(chuàng)建表
[self.queue inDatabase:^(FMDatabase *db) {
//創(chuàng)建表
BOOL createTableResult=[db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_student (id integer PRIMARY KEY AUTOINCREMENT,name text,age integer)"];
if (createTableResult) {
NSLog(@"創(chuàng)建表成功");
}else{
NSLog(@"創(chuàng)建表失敗");
}
}];
}
- (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) {
//獲取結(jié)果集,返回參數(shù)就是查詢結(jié)果
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;
}}];