文档章节

多线程操作FMDB的实践

云飞扬v5
 云飞扬v5
发布于 2016/06/27 20:03
字数 759
阅读 41
收藏 0

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

最近在弄项目的时候,需要多线程读写数据库,之前用的SQlite遇到多线程就不给力,很容易出现ACCESS_BAD的问题,于是找了些资料,发现FMDB的FMDBQueue可以比较容易的处理多线程的问题,所以就写了个demo

 

 

1,首先导入FMDB框架,可以采用cocoapods 管理依赖

对应的Podfile如下

platform :ios, '7.0'

pod 'AFNetworking', '~> 2.0'

pod 'FMDB', '~>2.2'

pod 'Masonry','~>0.6'

 

自己下载然后导入FMDB模块也是可以的

 

 

2,操作的学生类Student类有3个属性,学生ID,学生姓名和年龄。


 

#import <Foundation/Foundation.h>



@interface Student : NSObject



@property (nonatomic,copy) NSString *studentID;



@property (nonatomic,copy) NSString *studentName;



@property (nonatomic,strong) NSNumber *studentAge;



@end

 

3,创建GJFMDBQueueHelper的单例

 

- (id)init

{



    static id obj=nil;

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken,^{

        if ((obj =[super init])!=nil) {

            //创建表

            [self createDatabaseTable];



        }



    });

    self=obj;



    return  self;

}



+ (id)allocWithZone:(struct _NSZone *)zone

{

    // 里面的代码永远只执行1次

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        sharedHelper = [super allocWithZone:zone];

    });



    // 返回对象

    return sharedHelper;

}



+ (instancetype)sharedHelper

{

    // 里面的代码永远只执行1次

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        sharedHelper = [[self alloc] init];

    });



    // 返回对象

    return sharedHelper;

}



+ (id)copyWithZone:(struct _NSZone *)zone

{

    return sharedHelper;

}

 

 

4,创建表

-(BOOL)createDatabaseTable

{



    NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.sqlite",databaseName]];



    self.dbQueue = [FMDatabaseQueue databaseQueueWithPath:filePath];

    [self.dbQueue inDatabase:^(FMDatabase *db) {





        NSString *sql = @"CREATE TABLE IF NOT EXISTS t_students (student_id integer PRIMARY KEY AUTOINCREMENT,student_age integer NOT NULL,student_name text NOT NULL );";

        BOOL result= [db executeUpdate:sql];

        NSLog(@"%@",result?@"create table t_students success":@"create table t_students faiiled");





    }];

    return YES;

}

 

5实现数据库的增删改查方法

/*add */

-(BOOL)addNewStudentToDB:(Student *)student{



    __block BOOL insertResult=NO;

    [self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {



        [db open];

        NSString *sqlString=[NSString stringWithFormat:@"INSERT INTO t_students (student_name,student_age) VALUES ('%@',%ld)",

                             student.studentName,

                             [student.studentAge integerValue]];

        insertResult=[db executeUpdate:sqlString];

        [db close];



    }];



    return insertResult;





}

 

/* delete */

-(BOOL)deleteStudentByStudentID:(NSString *)studentID{

    __block BOOL result=NO;

    [self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {

        [db open];

        NSString *sqlString=[NSString stringWithFormat:@"DELETE FROM t_students WHERE student_id = %ld",[studentID integerValue]];

        result=[db executeUpdate:sqlString];

        [db close];

    }];



    return result;





}

 

/*update*/

-(BOOL)updateWithSQL:(NSString *)sqlString{



    NSLog(@"update sql==%@",sqlString);



    __block BOOL  updateResult=NO;





    [self.dbQueue inDatabase:^(FMDatabase *db)   {

        [db open];

        updateResult=[db executeUpdate:sqlString];

        [db close];



    }];



    return updateResult;



}

 

 

 

 

/*query */

-(NSArray *)modelsWithSQL:(NSString *)sqlString{

    __block NSMutableArray *eventModels=[NSMutableArray array];



    NSLog(@"query sql==%@",sqlString);

    [self.dbQueue inDatabase:^(FMDatabase *db)   {

        [db open];



        FMResultSet *rs = [db executeQuery:sqlString];

        while ([rs next])

        {

            //

            [eventModels addObject:[self modelFromRS :rs]];

        }

        [db close];

    }];

    return eventModels;



}


 

 

外部调用

 

 

在程序启动的时候判断是否有记录,如果没有的话,加入100条随机的数据 

  GJFMDBQueueHelper *fmdbHelper=[GJFMDBQueueHelper sharedHelper];

    NSArray *students=[fmdbHelper allStudents];

    if (students.count==0) {
        NSArray *nameArray=@[@"Jim",@"Mike",@"Lucy",@"Jessica"];
        for (int i=0; i<100; i++) {

            Student *student=[[Student alloc]init];
            student.studentName=nameArray[i%(nameArray.count-1)];
            student.studentAge=@(arc4random()%60+10);
            [fmdbHelper addNewStudentToDB:student];

        }
    }

 

 


  多线程测试

 


-(void)pressMTOButton{

    NSLog(@"test mutiple thread operation");



    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        //read



        GJFMDBQueueHelper *fmdbHelper=[GJFMDBQueueHelper sharedHelper];

        for (int i=0; i<100; i++) {

            Student *student=    [fmdbHelper studentWithStudentID:[NSString stringWithFormat:@"%d",i]];

            NSLog(@"111 first dispatch  studnet==%@",student);





        }



    });



    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        //write



        GJFMDBQueueHelper *fmdbHelper=[GJFMDBQueueHelper sharedHelper];



        for (int i=0; i<100; i++) {

            Student *student=[[Student alloc]init];

            student.studentName=@"StudentDemo";

            student.studentAge=@11;

            NSLog(@"222 second dispatch operation ==%@",student);



            [fmdbHelper addNewStudentToDB:student];

        }



    });



    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        //delete



        GJFMDBQueueHelper *fmdbHelper=[GJFMDBQueueHelper sharedHelper];

        for(int i=0;i<100;i++){



            NSArray *students=[fmdbHelper studentsWithStudentName:@"StudentDemo"];

            Student *student=students.firstObject;

            if (student) {

                [fmdbHelper deleteStudentByStudentID:student.studentID];

                NSLog(@"333 third dispatch operation %@",student);

            }



        }

    });



}

 

 

完整项目代码请在github中查看

https://github.com/knight314/FMDBStudentsDemo

喜欢的打颗星

参考文章和项目 

得找找了,参考了好几个人的代码

 

 

 

© 著作权归作者所有

云飞扬v5
粉丝 14
博文 105
码字总数 67465
作品 0
金华
私信 提问
数据库操作(FMDB)

iOS中原生的SQLite API在使用上相当不友好,在使用时,非常不便。于是,就出现了一系列将SQLite API进行封装的库,例如FMDB、PlausibleDatabase、sqlitepersistentobjects等,FMDB (https:/...

Snaiper
2016/01/28
135
0
FMDB | 实现数据的增删改查

一:介绍 FMDB是一个轻量级的数据库,用于将网络资源存储在本地。 项目中使用 ARC 还是 MRC,对使用 FMDB 都没有任何影响,FMDB 会在编译项目时自动匹配。 FMDB 将 SQLite API 进行了很友好的...

展菲
2018/11/30
0
0
iOS - 数据库 第三方框架FMDB

初识FMDB iOS中原生的 API在进行数据存储的时候,需要使用C语言中的函数,操作比较麻烦。于是,就出现了一系列将SQLite API进行封装的库,例如、、等。 FMDB是一款简洁、易用的封装库。因此,...

linweida
2016/09/20
23
0
iOS开发数据库篇—FMDB简单介绍

iOS开发数据库篇—FMDB简单介绍 一、简单说明 1.什么是FMDB FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API 2.FMDB的优点 使用起来更加面向对象,省去了很多麻烦、冗...

托楚齐坎基基
2015/12/30
227
0
iOS-SQLite3和FMDB使用

1 SQLite3 1> SQLite的语法 管理工具:Navicat 数据类型 { text 字段 integer 数字 real 浮点 bolb 二进制 可以完整保存数据,例如照片 } ddl(结构定义 CREATE ALTER DROP) { CREATE CREATE...

Ethan-GOGO
2015/10/11
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

为什么面试必问线程状态?你的回答满分了吗

看很多同学的面经、网上的面试资料,都不约而同的提到了一个基础问题:“你知道线程有几种状态吗?状态之间的扭转是怎样的?”,有准备的同学都知道有五种:New(新建)、Runnable(可运行)...

Z_J_H
29分钟前
4
0
如何保障云上数据安全?一文详解云原生全链路加密

点击下载《不一样的 双11 技术:阿里巴巴经济体云原生实践》 本文节选自《不一样的 双11 技术:阿里巴巴经济体云原生实践》一书,点击上方图片即可下载! 作者 李鹏(壮怀)阿里云容器服务高...

阿里巴巴云原生
29分钟前
3
0
获取数组的第一个元素

我有一个数组: array( 4 => 'apple', 7 => 'orange', 13 => 'plum' ) 我想获得此数组的第一个元素。 apple 预期结果: apple 一个要求: 它不能通过引用传递来完成 ,所以array_shift不是一......

javail
31分钟前
4
0
哈希情史知多少

<p align="right">——日拱一卒,不期而至!</p> 简介 hash是我们工作中经常听到的词,比如哈希表、哈希函数、hashCode、HashTable、HashMap等等,那么它们之间到底有怎样的爱恨情仇呢?来一...

彤哥读源码
38分钟前
4
0
SpringCloud 学习(5) --- Zuul(一)基本概念、配置

[TOC] Spring Cloud eureka:注册中心 服务端:提供注册 客户端:进行注册 ribbon:负载均衡(集群) Hystrix:熔断器,执行备选方案 Feign:远程调用 Zuul:网关,统一入口。 1.1、一夫当关,...

庭前云落
40分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部