FMDB的使用,如何利用FMDatabaseQueue保证线程安全
来源:互联网 发布:js简单计算器代码 编辑:程序博客网 时间:2024/05/27 14:14
原文地址1:http://www.w2bc.com/Article/18028
原文地址2:http://blog.csdn.net/xyz_lmn/article/details/9312837
FMDB的使用也许大家都不陌生,但是如果应用中使用了多线程操作数据库,那么就需要使用FMDatabaseQueue来保证线程安全了。 应用中不可在多个线程中共同使用一个FMDatabase对象操作数据库,这样会引起数据库数据混乱。 为了多线程操作数据库安全,FMDB使用了FMDatabaseQueue,使用FMDatabaseQueue很简单,首先用一个数据库文件地址来初使化FMDatabaseQueue,然后就可以将一个闭包(block)传入inDatabase方法中。 在闭包中操作数据库,而不直接参与FMDatabase的管理。
1)下载地址:https://github.com/ccgus/fmdb
2)注意点
——语句可以带分号“;”,也可以省略分号。
——同样需要添加“libsqlite3.dylib”库才能使用。
——移动端的开发中,一般不关闭数据库,即不怎么使用[self.db close];,因为每次重新打开比较耗性能,且每次程序关闭时数据库自然会同时关闭。
3)用法
#import "ViewController.h"#import "FMDB.h"@interface ViewController ()@property(nonatomic,strong) FMDatabase *db;- (IBAction)insert:(id)sender;- (IBAction)delete:(id)sender;- (IBAction)update:(id)sender;- (IBAction)select:(id)sender;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; 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); }}@end
(4)使用FMDatabaseQueue保证线程安全(建议以后都这么做)
——主要就是在创建数据库的时候,默认已经打开数据库
——随后的很多操作,因为需要在数据库中操作,所以需要利用队列的inDataBase方法调出数据库,在block中执行操作代码。
#import "ViewController.h"#import "FMDB.h"@interface ViewController ()@property(nonatomic,strong) FMDatabaseQueue *queue;- (IBAction)insert:(id)sender;- (IBAction)delete:(id)sender;- (IBAction)update:(id)sender;- (IBAction)select:(id)sender;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; 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); } }];}
5)如果要保证多个操作同时成功或者同时失败,用事务,即把多个操作放在同一个事务中。
——FMDB中,拿到数据库直接操作事务,如下:
- (IBAction)update:(id)sender { [self.queue inDatabase:^(FMDatabase *db) { [db beginTransaction]; [db executeUpdate:@"UPDATE t_student SET name='Jack' WHERE id=?",@2]; [db executeUpdate:@"UPDATE t_student SET name='Tomy' WHERE id=?",@3]; //发现情况不对时,主动回滚用下面语句。否则是根据commit结果,如成功就成功,如不成功才回滚 [db rollback]; [db executeUpdate:@"UPDATE t_student SET name='Eric' WHERE id=?",@4]; [db commit]; }];}
上面因为用的是FMDB封装好的,其实原生的代码是这样的:
[db executeUpdate:@"BEGIN TRANSACTION"];[db executeUpdate:@"ROLLBACK TRANSACTION"];[db executeUpdate:@"COMMIT TRANSACTION"];
——FMDB中,也可以直接利用队列进行事务操作,队列中的打开、关闭、回滚事务等都已经被封装好了。
- (IBAction)update:(id)sender { [self.queue inTransaction:^(FMDatabase *db, BOOL *rollback) { [db executeUpdate:@"UPDATE t_student SET name='Jack' WHERE id=?",@2]; [db executeUpdate:@"UPDATE t_student SET name='Tomy' WHERE id=?",@3]; //发现情况不对时,主动回滚用下面语句。 *rollback=YES; [db executeUpdate:@"UPDATE t_student SET name='Eric' WHERE id=?",@4]; }];}
- FMDB的使用,如何利用FMDatabaseQueue保证线程安全
- 【iOS开发-105】SQLite第三方框架FMDB的使用,以及使用FMDatabaseQueue保证线程安全
- FMDB使用Queue:FMDatabaseQueue
- 如何使用concurrent保证线程安全
- 如何保证线程安全?
- FMDB-FMDatabaseQueue
- FMDB-FMDatabaseQueue
- 线程安全的理解和如何保证线程安全
- FMDatabaseQueue为何会线程安全的一点心得
- 什么是线程安全?如何保证线程安全?
- 如何保证Java线程安全
- 如何保证ArrayList线程安全
- java如何保证线程安全
- FMDatabaseQueue的简单使用
- 单例模式下如何保证是线程安全的
- 在Java如何保证方法是线程安全的
- 使用正确的锁对象来保证线程安全
- 关于ThreadLocal如何保证数据线程安全
- System.Timers.Timer传参问题
- 以 primefaces.jar 来例说明,JBoss 如何加载 module 中的taglib
- jquery通过name,id,class取值或赋值
- ios 获取相机权限 判断相机状态
- java异常处理<3>__笔记(19)
- FMDB的使用,如何利用FMDatabaseQueue保证线程安全
- 诗人毛泽东
- c/c++宏定义的基本用法
- Best Time to Buy and Sell Stock II
- java -jar 与nohup的区别
- Mybatis+0+null,小问题引发的血案
- SVN常用命令之merge(合并)
- 华为oj 密码验证合格程序
- 图像直方图相关总结