现在ios里使用的数据库一般都是Sqlite,但是使用Sqlite有个不太好的地方就是在多线程的时候,会出现问题,sqlite只能打开一个读或者写连结。这样的话多线程就会碰到资源占用的问题。

最开始是使用FMDB,FMDB的早期版本不能解决这个问题,后来FMDB更新了,新版本的FMDB能够很好的解决这个多线程使用Sqlite 。

FMDB github网址  https://github.com/ccgus/fmdb 最新版的请到github取下载。

本文演示了使用FMDB通过多线程来读和写数据库操作。

1.建立数据库表,我采用的是Firefox的Sqlite manager 来建立的。

建表sql如下

CREATE TABLE "tbl_user" ("_id" INTEGER PRIMARY KEY  AUTOINCREMENT  NOT NULL , "name" VARCHAR(30), "password" VARCHAR(30))

 2. 建立数据表的映射实体UserEntity


#import <Foundation/Foundation.h>

@interface UserEntity : NSObject
{
    int _id;
    NSString *name;
    NSString *password;
} @property (nonatomic, assign)int ID;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *password;

@end

3. 建立操作数据库的dao


//
//  DbDao.m
//  SqliteTest
//
//  Created by foxwang on 12-4-9.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
// #import "DbDao.h"
#import "DbFileManager.h" #import "FMDatabase.h"
#import "FMDatabaseAdditions.h"
#import "FMDatabasePool.h"
#import "FMDatabaseQueue.h"
#import "UserEntity.h" static DbDao *gSharedInstance = nil; @implementation DbDao
@synthesize dbFile;
@synthesize dbQueue; +(DbDao *)sharedInstance
{
    @synchronized(self)
    {
        if (gSharedInstance == nil)
            gSharedInstance = [[DbDao alloc] init];
    }
    return gSharedInstance;    
} - (void)dealloc
{
    [self.dbFile release];
    self.dbQueue = nil;
    [super dealloc];
} - (id)init
{
    
    self = [super init];
    if (self)
    {
        self.dbFile = [DbFileManager dbFilePath];
        self.dbQueue = [FMDatabaseQueue databaseQueueWithPath:self.dbFile];
        
        
    }
    return  self;
} - (UserEntity *)rsToUser:(FMResultSet*)rs
{
    UserEntity *user = [[[UserEntity alloc] init] autorelease];
    user.ID = [rs intForColumn:@"_id"];
    user.name = [rs stringForColumn:@"name"];
    user.password = [rs  stringForColumn:@"password"];
    return user;
} - (void)addUser:(UserEntity *)user
{
    [self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
        [db open];
        NSString *sql = @"insert into tbl_user(name, password) values (?, ?)";
        [db executeUpdate:sql,user.name, user.password];
        [db close];
    }];  
} - (NSArray *)getUsers;
{
    __block NSMutableArray *users = [[[NSMutableArray alloc] init] autorelease];  
    [self.dbQueue inDatabase:^(FMDatabase *db)   {
        [db open];
        NSString *sql = @"select * from tbl_user ";
        FMResultSet *rs = [db executeQuery:sql];
        while ([rs next])
        {
            [users addObject:[self rsToUser :rs]]; 
        }
        [db close];
    }];
    return users;
}

@end

4. 编写测试方法

在didFinishLaunchingWithOptions 方法里启动3个线程 :2个线程写,1个线程读

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions


{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    
    
    [NSThread detachNewThreadSelector:@selector(writeDbOne) toTarget:self withObject:nil];
    
    [NSThread detachNewThreadSelector:@selector(readDb) toTarget:self withObject:nil];
    
    [NSThread detachNewThreadSelector:@selector(writeDbTwo) toTarget:self withObject:nil];
    
    return YES;
}

- (void)writeDbOne
{
    DbDao *dao = [DbDao  sharedInstance];
    for (int i = 0; i < 500; i++)
    {
        @autoreleasepool 
        {
             UserEntity *user = [[[UserEntity alloc] init] autorelease];
             user.name = [NSString stringWithFormat:@"name %d", i];
             user.password = [NSString stringWithFormat:@"password %d", i];
             [dao addUser:user];
             NSLog(@"writeDbOne %d ", i);
        }
       
    }
} - (void)writeDbTwo
{
    DbDao *dao = [DbDao  sharedInstance];
    for (int i = 600; i < 1200; i++)
    {
        @autoreleasepool 
        {
            UserEntity *user = [[[UserEntity alloc] init] autorelease];
            user.name = [NSString stringWithFormat:@"name %d", i];
            user.password = [NSString stringWithFormat:@"password %d", i];
            [dao addUser:user];
            NSLog(@"writeDbTwo %d ", i);
        }
        
    }
} - (void)readDb
{
     DbDao *dao = [DbDao  sharedInstance];
     NSArray *users =   [dao getUsers];
     NSLog(@"%@", users);

}

最后查看数据库信息,数据成功插入

结论 :使用新的FMDB ,很好的解决了多线程问题

项目文件下载

FMDB多线程读写问题,使用FMDataBaseQueue操作可以解决同时打开一个链接de读写问题的更多相关文章

  1. C#打开一个文本文件并读写

    OpenFileDialog OFD = new OpenFileDialog(); OFD.Title = "打开第一个文本文件"; OFD.FileName = "* ...

  2. Python文件操作:文件的打开关闭读取写入

    Python文件操作:文件的打开关闭读取写入 一.文件的打开关闭 Python能以文本和二进制两种方式处理文件,本文主要讨论在Python3中文本文件的操作. 文件操作都分为以下几个步骤: 1.打开文 ...

  3. 使用FMDB多线程访问数据库,及database is locked的问题

    每日更新关注:http://weibo.com/hanjunqiang  新浪微博 今天终于解决了多线程同时访问数据库时,报数据库锁定的问题,错误信息是: Unknown error finalizi ...

  4. 使用FMDB多线程訪问数据库,及database is locked的问题

    今天最终攻克了多线程同一时候訪问数据库时,报数据库锁定的问题.错误信息是: Unknown error finalizing or resetting statement (5: database i ...

  5. Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步

    Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步 一.概述     PV操作是对信号量进行的操作.     进程同步是指在并发进程之间存在一种制约关系,一个进程的执行依赖另一个进程的消 ...

  6. C#操作Excel(创建、打开、读写、保存)几种方法的总结

    在.NET开发中,不管是web程序还是桌面软件(尤其是涉及数据库操作的MIS系统等),常常需操作Excel,如导出数据到Excel,读取Excel中数据到程序中等.总结起来,其操作不外乎创建.打开.读 ...

  7. QSettings配置读写-win注册表操作-ini文件读写

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSettings配置读写-win注册表操作-ini文件读写     本文地址:http:// ...

  8. Python基础笔记系列十一:标准输入输出、文件读写和指针等操作

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! 标准输入输出一.输入 在sublime中这个时候需要安装SublimeRE ...

  9. Win8 Metro中文件读写删除与复制操作

    Win8Metro中,我们不能在向以前那样调用WIN32的API函数来进行文件操作,因此,下面就来介绍一下Win8 Metro中文件的读写操作. 1 Windows 8 Metro Style App ...

随机推荐

  1. 我的第一份vim程序

    vim太好用了吧!!!根本停不下来啊! devc++再见! /*==================================================================== ...

  2. Delphi实现WebService带身份认证的数据传输

    WebService使得不同开发工具开发出来的程序可以在网络连通的环境下相互通信,它最大的特点就是标准化(基于XML的一系列标准)带来的跨平台.跨开发工具的通用性,基于HTTP带来的畅通无阻的能力(跨 ...

  3. 用Delphi7开发Web Service程序 转

        转:http://rosehacker.blog.51cto.com/2528968/450160 用Delphi7开发Web Service程序,并把服务程序放在IIS Web服务器上提供给 ...

  4. 《JavaScript核心概念》基础部分重点摘录

    注:<JavaScript核心概念>适合深入了解JavaScript,比我买的<JavaScript框架设计>语言和内容丰富多了(可能是我水平尚浅吧). 1. 作用域 var ...

  5. Hibernate(一)JDBC简介

    在了解Hibernate之前,我们先回顾一下传统JDBC访问数据库的相关内容.重点在于分析JDBC访问存在哪些 缺陷,这些缺陷在Hibernate中是如何思考和解决的? JDBC主要对象 DriveM ...

  6. HDOJ1253 胜利大逃亡 BFS

    胜利大逃亡 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submiss ...

  7. if语句,if...else if语句和switch...case语句的区别和分析

    前段时间在工作中遇到了一个关于条件判断语句的问题,在if语句,if else if语句和switch case语句这三者之间分析,使用其中最有效率的一种方法. 所以就将这个问题作为自己第一篇博客的主要 ...

  8. 第二十三章、软件安装: RPM, SRPM 与 YUM 功能

    SRPM 的使用 : rpmbuild 包含Source code 的 SRPM 新版的 rpm 已经将 RPM 与 SRPM 的命令分开了,SRPM 使用的是 rpmbuild 这个命令,而不是 r ...

  9. 回某位朋友问题备受phpcgi.exe煎熬现在cpu跑满(解决方案)

    (本文原创,但是cgi参数参考一个大神写的针对小服务器的,希望大家积极投票哦) 下面是对php-cgi.ext过多引起服务器cup%的解决方法,希望对大家有帮助;大多数情况是发生在第四项上;   解决 ...

  10. mysql中group_concat函数用法

    该函数返回带有来自一个组的连接的非NULL值的字符串结果.该函数是一个增强的Sybase SQL Anywhere支持的基本LIST()函数. 语法结构: GROUP_CONCAT([DISTINCT ...