- iOS中原生的SQLite API在进行数据存储的时候, 需要使用C语言中的函数, 操作比较繁琐. 于是, 就出现了一系列将SQLite API进行封装的库, 例如
FMDB,PlausibleDatabase,SQLitePersistObjects
等. - FMDB是一款简洁, 易用的封装库. 因此, 在这里推荐使用第三方框架FMDB,它是对
libsqlite3
框架的封装, 用起来的步骤与 SQLite 使用类似, 并且对于多线程的并发操作进行了处理, 所以线程是安全的.
优点:
1.对多线程的并发操作进行处理, 所以线程安全的;
2.以OC的方式封装了SQLite的C语言API, 使用起来更加方便
3.FMDB是轻量级的框架, 使用灵活
**缺点: **
因为他是OC的语言封装的,只能在iOS开发中使用,在扩平台操作的时候存在局限性.
FMDB中重要的类
FMDatabase
: 一个FMDatabase对象就代表一个单独的SQLite数据库, 用来执行SQL语句
FMResultSet
: 使用FMDatabase执行查询后的结果集
FMDatabaseQueue
: 用于在多线程中执行多个查询或更新, 它是线程安全的
**步骤: **
1.下载FMDB文件 , 将FMDB文件添加到工程中
2.导入libsqlite3.0.tbd框架,导入头文件FMDatabase.h
3.代码实现,与SQLite使用步骤相似, 创建数据库路径,获得数据库路径, 打开数据库,然后对数据库进行增删改查,关闭数据库.
代码实现:
- (void)createtable
{
NSString *string = @"create table if not exists person(id integer primary key autoincrement not null, name text, age integer, gender text)";
NSString *documentsPathStr = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
NSString *stringPath = [documentsPathStr stringByAppendingPathComponent:@"person.sqlite"];
//初始化数据库
self.dataBase = [FMDatabase databaseWithPath:stringPath];
//判断数据库是否打开
if ([self.dataBase open])
{
BOOL result = [self.dataBase executeUpdate:string];
if (result)
{
NSLog(@"建表成功");
}else
{
NSLog(@"建表失败");
}
}
[self.dataBase close];
}
- (void)insertToObject{
NSString *string = @"insert into person (name, age, gender)values('aaa', 18, 'm')";
if ([self.dataBase open]) {
BOOL request = [self.dataBase executeUpdate:string];
if (request) {
NSLog(@"插入成功");
}else { NSLog(@"插入失败");
}
}
[self.dataBase close];
}
- (void)deleteObject{
NSString *string = @"delete from person where age = 18";
if ([self.dataBase open])
{
BOOL request = [self.dataBase executeUpdate:string];
if (request) {
NSLog(@"删除成功");
}else {
NSLog(@"删除失败");
}
}
[self.dataBase close];}
- (void)updateObject{
NSString *string = @"update person set name = 'bbb', gender = 'w' where age = 18";
if ([self.dataBase open]) {
BOOL result = [self.dataBase executeUpdate:string];
if (result) {
NSLog(@"改成功");
}else {
NSLog(@"改失败");
} }
[self.dataBase close];
}
- (void)searchAll{
NSString *string = @"select * from person";
if ([self.dataBase open])
{ FMResultSet *result = [self.dataBase executeQuery:string];
while ([result next]) {
NSString *name = [result objectForColumnName:@"name"];
NSInteger age = [result intForColumn:@"age"]; NSLog(@"%@", name);
NSLog(@"%ld", age);
}
}
[self.dataBase close];
}
**多线程中使用: **
如果应用中使用了多线程操作数据库, 那么久需要使用FMDatabaseQueue来保证现场安全了, 应用中不可再多个现场中共同使用一个FMDatabase对象操作数据库,这样会引起数据库数据混乱.多线程更新相同的字眼导致数据竞争时使用等待队列(等待现在执行的处理结束)
- (void)insertObject{
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:self.fileName];
[self.dataBase open];
__block BOOL isSucceed = true;
//再这里执行任务
// 给isSucceed赋值, 但是要判断之前的状态, 如果这条执行失败了, 那么只会的会受到影响
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
isSucceed = [db executeUpdate:@"insert into person (name, age, gender)values('aaa', 18, 'm')"] && isSucceed; }];
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
isSucceed = [db executeUpdate:@"insert into person (name, age, gender)values('aaa', 18, 'm')"] && isSucceed; }];
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
isSucceed = [db executeUpdate:@"insert into person (name, age, gender)values('aaa', 18, 'm')"] && isSucceed; }];
}