zoukankan      html  css  js  c++  java
  • FMDB多线程读写问题,使用FMDataBaseQueue操作可以解决同时打开一个链接de读写问题

    现在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 ,很好的解决了多线程问题

    项目文件下载

  • 相关阅读:
    小技巧与阅读感悟
    Android常见漏洞介绍(1):Intent Scheme URL 攻击
    利用Mallet工具自动挖掘文本Topic
    Xie Tao的几个小建议PPT:关于读Paper,如何与他人交流,赶Deadline
    Python解析DNS数据包
    iOS 横竖屏适配 笔记
    多工程联编,cocopods的使用
    Call to unavailable function 'system': not available on iOS
    xxx referenced from: xxx in xxx.o
    YYModel学习总结YYClassInfo(1)
  • 原文地址:https://www.cnblogs.com/ccguo/p/3453828.html
Copyright © 2011-2022 走看看