qileilove

blog已经转移至github,大家请访问 http://qaseven.github.io/

iOS开发之FMDB

  sqlite作为一个轻量级的数据库,由于它占用的内存很少,因此在很多的嵌入式设备中得到广泛的使用。iOS的SDK很早就开始支持了SQLite,我们只需要加入 libsqlite3.dylib 以及引入 sqlite3.h 头文件即可,但由于原生sqlite的API不是很友好,因此使用的话一般会对其做一层封装,其中以开源的FMDB最为流行。
  FMDB主要的类
  1.FMDatabase – 表示一个单独的SQLite数据库。 用来执行SQLite的命令。
  2.FMResultSet – 表示FMDatabase执行查询后结果集
  3.FMDatabaseQueue – 当你在多线程中执行操作,使用该类能确保线程安全。
  FMDB的使用
  数据库的创建:
  创建FMDatabase对象时需要参数为SQLite数据库文件路径。该路径可以是以下三种之一:
  1..文件路径。该文件路径无需真实存,如果不存在会自动创建。
  2..空字符串(@”")。表示会在临时目录创建一个临时数据库,当FMDatabase 链接关闭时,文件也被删除。
  3.NULL. 将创建一个内存数据库。同样的,当FMDatabase连接关闭时,数据会被销毁。
  内存数据库:
  通常数据库是存放在磁盘当中的。然而我们也可以让存放在内存当中的数据库,内存数据库的优点是对其操作的速度较快,毕竟访问内存的耗时低于访问磁盘,但内存数据库有如下缺陷:由于内存数据库没有被持久化,当该数据库被关闭后就会立刻消失,断电或程序崩溃都会导致数据丢失;不支持读写互斥处理,需要自己手动添加锁;无法被别的进程访问。
  临时数据库:
  临时数据库和内存数据库非常相似,两个数据库连接创建的临时数据库也是各自独立的,在连接关闭后,临时数据库将自动消失,其底层文件也将被自动删除。尽管磁盘文件被创建用于存储临时数据库中的数据信息,但是实际上临时数据库也会和内存数据库一样通常驻留在内存中,唯一不同的是,当临时数据库中数据量过大时,SQLite为了保证有更多的内存可用于其它操作,因此会将临时数据库中的部分数据写到磁盘文件中,而内存数据库则始终会将数据存放在内存中。
  创建数据库:FMDatabase *db= [FMDatabase databaseWithPath:dbPath] ;
  在进行数据库的操作之前,必须要先把数据库打开,如果资源或权限不足无法打开或创建数据库,都会导致打开失败。
  如下为创建和打开数据库的示例:
  NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  NSString *documentDirectory = [paths objectAtIndex:0];
  //dbPath: 数据库路径,存放在Document中。
  NSString *dbPath = [documentDirectory stringByAppendingPathComponent:@"MYTest.db"];
  //创建数据库实例 db  这里说明下:如果路径中不存在"MYTest.db"的文件,sqlite会自动创建"MYTest.db"
  FMDatabase *db= [FMDatabase databaseWithPath:dbPath] ;
  if (![db open]) {
  NSLog(@"Could not open db.");
  return ;
  }
  更新操作
  一切不是SELECT命令都视为更新操作,包括CREATE, UPDATE, INSERT,ALTER,COMMIT, BEGIN, DETACH, DELETE, DROP, END, EXPLAIN, VACUUM和REPLACE等。
  创建表:
  [db executeUpdate:@"CREATE TABLE myTable (Name text,Age integer)"];
  插入
  [db executeUpdate:@"INSERT INTO myTable (Name,Age) VALUES (?,?)",@"jason",[NSNumber numberWithInt:20]];
  更新
  [db executeUpdate:@"UPDATE myTable SET Name = ? WHERE Name = ? ",@"john",@"jason"];.
  删除
  [db executeUpdate:@"DELETE FROM myTable WHERE Name = ?",@"jason"];
  查询操作
  SELECT命令就是查询,执行查询的方法是以 -excuteQuery开头的。执行查询时,如果成功返回FMResultSet对象, 错误返回nil. 读取信息的时候需要用while循环:
  FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"];
  while ([s next]) {
  //从每条记录中提取信息
  }
  关闭数据库
  当使用完数据库,你应该 -close 来关闭数据库连接来释放SQLite使用的资源。
  [db close];
  参数
  通常情况下,你可以按照标准的SQL语句,用?表示执行语句的参数,如:
  INSERT INTO myTable VALUES (?, ?, ?)
  然后,可以我们可以调用executeUpdate方法来将?所指代的具体参数传入,通常是用变长参数来传递进去的,如下:
  NSString *sql = @"insert into myTable (name, password) values (?, ?)";
  [db executeUpdate:sql, user.name, user.password];
  这里需要注意的是,参数必须是NSObject的子类,所以象int,double,bool这种基本类型,需要进行相应的封装
  [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:42]];

多线程操作
  由于FMDatabase对象本身不是线程安全的,因此为了避免在多线程操作的时候出错,需要使用 FMDatabaseQueue来执行相关操作。只需要利用一个数据库文件地址来初使化FMDatabaseQueue,然后传入一个block到inDatabase中,即使是多个线程同时操作,该queue也会确保这些操作能按序进行,保证线程安全。
  创建队列:
  FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];
  使用方法:
[queue inDatabase:^(FMDatabase *db) {
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
FMResultSet *rs = [db executeQuery:@"select * from foo"];
while([rs next]) {
}
}];
  至于事务可以像这样处理:
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];
if (somethingWrongHappened) {
*rollback = YES;
return;
}
// etc…
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];
}];

posted on 2014-12-08 22:00 顺其自然EVO 阅读(1434) 评论(0)  编辑  收藏 所属分类: 测试学习专栏数据库


只有注册用户登录后才能发表评论。


网站导航:
 
<2014年12月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜