IOS多线程读写Sqlite问题解决

现在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

 

01. #import <Foundation/Foundation.h>
02.  
03. @interface UserEntity : NSObject
04. {
05. int _id;
06. NSString *name;
07. NSString *password;
08. }
09.  
10. @property (nonatomic, assign)int ID;
11. @property (nonatomic, retain) NSString *name;
12. @property (nonatomic, retain) NSString *password;
13. @end

3. 建立操作数据库的dao

 

01. //
02. //  DbDao.m
03. //  SqliteTest
04. //
05. //  Created by foxwang on 12-4-9.
06. //  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
07. //
08.  
09. #import "DbDao.h"
10. #import "DbFileManager.h"
11.  
12. #import "FMDatabase.h"
13. #import "FMDatabaseAdditions.h"
14. #import "FMDatabasePool.h"
15. #import "FMDatabaseQueue.h"
16. #import "UserEntity.h"
17.  
18. static DbDao *gSharedInstance = nil;
19.  
20. @implementation DbDao
21. @synthesize dbFile;
22. @synthesize dbQueue;
23.  
24. +(DbDao *)sharedInstance
25. {
26. @synchronized(self)
27. {
28. if (gSharedInstance == nil)
29. gSharedInstance = [[DbDao alloc] init];
30. }
31. return gSharedInstance;   
32. }
33.  
34. - (void)dealloc
35. {
36. [self.dbFile release];
37. self.dbQueue = nil;
38. [super dealloc];
39. }
40.  
41. - (id)init
42. {
43.  
44. self = [super init];
45. if (self)
46. {
47. self.dbFile = [DbFileManager dbFilePath];
48. self.dbQueue = [FMDatabaseQueue databaseQueueWithPath:self.dbFile];
49.  
50.  
51. }
52. return  self;
53. }
54.  
55. - (UserEntity *)rsToUser:(FMResultSet*)rs
56. {
57. UserEntity *user = [[[UserEntity alloc] init] autorelease];
58. user.ID = [rs intForColumn:@"_id"];
59. user.name = [rs stringForColumn:@"name"];
60. user.password = [rs  stringForColumn:@"password"];
61. return user;
62. }
63.  
64. - (void)addUser:(UserEntity *)user
65. {
66. [self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
67. [db open];
68. NSString *sql = @"insert into tbl_user(name, password) values (?, ?)";
69. [db executeUpdate:sql,user.name, user.password];
70. [db close];
71. }]; 
72. }
73.  
74. - (NSArray *)getUsers;
75. {
76. __block NSMutableArray *users = [[[NSMutableArray alloc] init] autorelease]; 
77. [self.dbQueue inDatabase:^(FMDatabase *db)   {
78. [db open];
79. NSString *sql = @"select * from tbl_user ";
80. FMResultSet *rs = [db executeQuery:sql];
81. while ([rs next])
82. {
83. [users addObject:[self rsToUser :rs]];
84. }
85. [db close];
86. }];
87. return users;
88. }
89. @end

4. 编写测试方法

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

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

 

01. {
02. self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
03. // Override point for customization after application launch.
04. self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];
05. self.window.rootViewController = self.viewController;
06. [self.window makeKeyAndVisible];
07.  
08.  
09. [NSThread detachNewThreadSelector:@selector(writeDbOne) toTarget:self withObject:nil];
10.  
11. [NSThread detachNewThreadSelector:@selector(readDb) toTarget:self withObject:nil];
12.  
13. [NSThread detachNewThreadSelector:@selector(writeDbTwo) toTarget:self withObject:nil];
14.  
15. return YES;
16. }

01. - (void)writeDbOne
02. {
03. DbDao *dao = [DbDao  sharedInstance];
04. for (int i = 0; i < 500; i++)
05. {
06. @autoreleasepool
07. {
08. UserEntity *user = [[[UserEntity alloc] init] autorelease];
09. user.name = [NSString stringWithFormat:@"name %d", i];
10. user.password = [NSString stringWithFormat:@"password %d", i];
11. [dao addUser:user];
12. NSLog(@"writeDbOne %d ", i);
13. }
14.  
15. }
16. }
17.  
18. - (void)writeDbTwo
19. {
20. DbDao *dao = [DbDao  sharedInstance];
21. for (int i = 600; i < 1200; i++)
22. {
23. @autoreleasepool
24. {
25. UserEntity *user = [[[UserEntity alloc] init] autorelease];
26. user.name = [NSString stringWithFormat:@"name %d", i];
27. user.password = [NSString stringWithFormat:@"password %d", i];
28. [dao addUser:user];
29. NSLog(@"writeDbTwo %d ", i);
30. }
31.  
32. }
33. }
34.  
35. - (void)readDb
36. {
37. DbDao *dao = [DbDao  sharedInstance];
38. NSArray *users =   [dao getUsers];
39. NSLog(@"%@", users);
40. }

\
 

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

源码下载:http://down1.it165.net/pro/201204/0409SqliteTest.zip

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值