|
转载自:http://www.cnblogs.com/likwo/archive/2012/04/09/2438790.html
现在ios里使用的数据库一般都是Sqlite,但是使用Sqlite有个不太好的地方就是在多线程的时候,会出现问题,sqlite只能打开一个读或者写连结。这样的话多线程就会碰到资源占用的问题。
最开始是使用FMDB,FMDB的早期版本不能解决这个问题,后来FMDB更新了,新版本的FMDB能够很好的解决这个多线程使用Sqlite 。
FMDB github网址 https://github.com/ccgus/fmdb 最新版的请到github取下载。
本文演示了使用FMDB通过多线程来读和写数据库操作。
1.建立数据库表,我采用的是Firefox的Sqlite manager 来建立的。
建表sql如下
CREATETABLE"tbl_user"("_id"INTEGERPRIMARYKEYAUTOINCREMENTNOTNULL,"name"VARCHAR(30),"password"VARCHAR(30))
2. 建立数据表的映射实体UserEntity
#import<Foundation/Foundation.h>
@interfaceUserEntity:NSObject
{
int_id;
NSString*name;
NSString*password;
}
@property(nonatomic,assign)intID;
@property(nonatomic,retain)NSString*name;
@property(nonatomic,retain)NSString*password;
@end
3. 建立操作数据库的dao
//
//DbDao.m
//SqliteTest
//
//Createdbyfoxwangon12-4-9.
//Copyright(c)2012年__MyCompanyName__.Allrightsreserved.
//
#import"DbDao.h"
#import"DbFileManager.h"
#import"FMDatabase.h"
#import"FMDatabaseAdditions.h"
#import"FMDatabasePool.h"
#import"FMDatabaseQueue.h"
#import"UserEntity.h"
staticDbDao*gSharedInstance=nil;
@implementationDbDao
@synthesizedbFile;
@synthesizedbQueue;
+(DbDao*)sharedInstance
{
@synchronized(self)
{
if(gSharedInstance==nil)
gSharedInstance=[[DbDaoalloc]init];
}
returngSharedInstance;
}
-(void)dealloc
{
[self.dbFilerelease];
self.dbQueue=nil;
[superdealloc];
}
-(id)init
{
self=[superinit];
if(self)
{
self.dbFile=[DbFileManagerdbFilePath];
self.dbQueue=[FMDatabaseQueuedatabaseQueueWithPath:self.dbFile];
}
returnself;
}
-(UserEntity*)rsToUser:(FMResultSet*)rs
{
UserEntity*user=[[[UserEntityalloc]init]autorelease];
user.ID=[rsintForColumn:@"_id"];
user.name=[rsstringForColumn:@"name"];
user.password=[rsstringForColumn:@"password"];
returnuser;
}
-(void)addUser:(UserEntity*)user
{
[self.dbQueueinTransaction:^(FMDatabase*db,BOOL*rollback){
[dbopen];
NSString*sql=@"insertintotbl_user(name,password)values(?,?)";
[dbexecuteUpdate:sql,user.name,user.password];
[dbclose];
}];
}
-(NSArray*)getUsers;
{
__blockNSMutableArray*users=[[[NSMutableArrayalloc]init]autorelease];
[self.dbQueueinDatabase:^(FMDatabase*db){
[dbopen];
NSString*sql=@"select*fromtbl_user";
FMResultSet*rs=[dbexecuteQuery:sql];
while([rsnext])
{
[usersaddObject:[selfrsToUser:rs]];
}
[dbclose];
}];
returnusers;
}
@end
4. 编写测试方法
在didFinishLaunchingWithOptions方法里启动3个线程 :2个线程写,1个线程读
-(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
self.window=[[[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]bounds]]autorelease];
//Overridepointforcustomizationafterapplicationlaunch.
self.viewController=[[[ViewControlleralloc]initWithNibName:@"ViewController"bundle:nil]autorelease];
self.window.rootViewController=self.viewController;
[self.windowmakeKeyAndVisible];
[NSThreaddetachNewThreadSelector:@selector(writeDbOne)toTarget:selfwithObject:nil];
[NSThreaddetachNewThreadSelector:@selector(readDb)toTarget:selfwithObject:nil];
[NSThreaddetachNewThreadSelector:@selector(writeDbTwo)toTarget:selfwithObject:nil];
returnYES;
}
-(void)writeDbOne
{
DbDao*dao=[DbDaosharedInstance];
for(inti=0;i<500;i++)
{
@autoreleasepool
{
UserEntity*user=[[[UserEntityalloc]init]autorelease];
user.name=[NSStringstringWithFormat:@"name%d",i];
user.password=[NSStringstringWithFormat:@"password%d",i];
[daoaddUser:user];
NSLog(@"writeDbOne%d",i);
}
}
}
-(void)writeDbTwo
{
DbDao*dao=[DbDaosharedInstance];
for(inti=600;i<1200;i++)
{
@autoreleasepool
{
UserEntity*user=[[[UserEntityalloc]init]autorelease];
user.name=[NSStringstringWithFormat:@"name%d",i];
user.password=[NSStringstringWithFormat:@"password%d",i];
[daoaddUser:user];
NSLog(@"writeDbTwo%d",i);
}
}
}
-(void)readDb
{
DbDao*dao=[DbDaosharedInstance];
NSArray*users=[daogetUsers];
NSLog(@"%@",users);
}
最后查看数据库信息,数据成功插入
结论 :使用新的FMDB ,很好的解决了多线程问题。 |
|
|