sqlite数据库是ios开发中经常使用到的数据持久化方案,因为项目需求的不同,对数据库操作的要求也不同。
由于最近使用sqlite时,有一些地方需要频繁的更新,这时在多线程操作时,其他线程访问数据库会造成程序崩溃,因为之前的框架里设计的数据库管理工具类采用的是单例模式,这样在多线程操作同一个数据库时很容易引起冲突,导致程序崩溃,所以开始寻找多线程下线程安全的办法。
其实FMDB本身已经对多线程做了考虑,FMDatabaseQueue就是为了解决数据库操作线程安全的,只是由于之前框架集成的单例操作,并且没有设计多线程访问,所以并没有发生这个问题。
FMDatabaseQueue解决线程安全的操作方法:
FMDatabaseQueue使用下面这个函数对数据库进行操作,通过描述可知,这样等于是把数据库的操作放到一个串行队列中,从而保证不会在同一时间对数据库做改动。
/**?Synchronously?perform?database?operations?on?queue.
?@param?block?The?code?to?be?run?on?the?queue?of?`FMDatabaseQueue`
?*/ ?
-?(void)inDatabase:(void?(^)(FMDatabase?*db))block;
FMDatabaseQueue要使用单例创建,这样多线程调用时,数据库操作使用一个队列,保证线程安全。
@interface?DBHelper?:?NSObject??
/**
?*??数据库操作队列
?*/?
@property(nonatomic,retain,readonly)FMDatabaseQueue *dbQueue;/** * 获取数据库管理类单例 */+(DBHelper *)sharedHelper;
在.m中实现单例创建(不做赘述),并重写dbQueue的get方法
//lazy?load??
-(FMDatabaseQueue?*)dbQueue{??
if?(!_dbQueue)?{??
_dbQueue?=?[FMDatabaseQueue?databaseQueueWithPath:DB_PATH];??
????}??
return?_dbQueue;??
}?
操作数据库时,通过单例的dbQueue在block内执行SQL操作,block属于同步执行,执行完之后才会跳出执行操作之后的语句
DBHelper?*dbHelper?=?[DBHelper?sharedHelper];??
__blockBOOL?res?=?NO;??
[dbHelper.dbQueue?inDatabase:^(FMDatabase?*db)?{??
NSString?*sql?=?[NSString?stringWithFormat:@"INSERT?INTO?%@(%@)?VALUES?(%@);",?tableName,?keyString,?valueString];??
res?=?[db?executeUpdate:sql?withArgumentsInArray:insertValues];??
self.pk?=?res?[NSNumber?numberWithLongLong:db.lastInsertRowId].intValue:0;??
NSLog(res?@"插入成功":@"插入失败");??
????}];??
return?res;?
注意:因为队列是串行执行的,因此inDatabase的block并不能嵌套使用,这样会导致错误。
了解了多线程下使用FMDatabaseQueue的操作原理就可以创建一个管理类对模型数据的存取查删进行统一管理,可以使用工具类操作,也可以创建集成NSObject的子类进行管理,需要存取的模型类继承此子类即可。
代码:
#import?? <objc/runtime.h>
/**?SQLite五种数据类型?*/??
#define?SQLTEXT?????@"TEXT"??
#define?SQLINTEGER??@"INTEGER"??
#define?SQLREAL?????@"REAL"??
#define?SQLBLOB?????@"BLOB"??
#define?SQLNULL?????@"NULL"??
#define?PrimaryKey??@"primary?key"??
#define?primaryId???@"pk" ?
/**
?*??数据库对象的父类
?*/??
@interface?DBBaseModel?:?NSObject??
/**?主键?id?*/??
@property?(nonatomic,?assign)???int????????pk;??
@property(nonatomic,copy)NSString?*keyWord;?????????????????//查表的关键字字段??
/**?列名?*/??
@property?(retain,?readonly,?nonatomic)?NSMutableArray?????????*columeNames;??
/**?列类型?*/??
@property?(retain,?readonly,?nonatomic)?NSMutableArray?????????*columeTypes;??
#pragma?--mark?functions??
/**
?*??获取该类(模型)中的所有属性?runtime
?*
?*/??
+?(NSDictionary?*)getPropertys;??
/**?获取所有属性,包括主键?*/??
+?(NSDictionary?*)getAllProperties;??
/**?数据库中是否存在表?*/??
+?(BOOL)isExistInTable;??
/**?表中的字段*/??
+?(NSArray?*)getColumns;??
/**?保存或更新
?*?如果不存在主键,保存,
?*?有主键,则更新
?*/??
-?(BOOL)saveOrUpdate;??
/**?保存单个数据?*/??
-?(BOOL)save;??
/**?批量保存数据?*/??
+?(BOOL)saveObjects:(NSArray?*)array;??
/**?更新单个数据?*/??
-?(BOOL)update;??
/**?批量更新数据*/??
+?(BOOL)updateObjects:(NSArray?*)array;??
/**?删除单个数据?*/??
-?(BOOL)deleteObject;??
/**?批量删除数据?*/??
+?(BOOL)deleteObjects:(NSArray?*)array;??
/**?通过条件删除数据?*/??
+?(BOOL)deleteObjectsByCriteria:(NSString?*)criteria;??
/**?清空表?*/??
+?(BOOL)clearTable;??
/**?查询全部数据?*/??
+?(NSArray?*)findAll;??
/**?通过主键查询?*/??
+?(instancetype)findByPK:(int)inPk;??
/**?查找某条数据?*/??
+?(instancetype)findFirstByCriteria:(NSString?*)criteria;??
//?值?为?通过?条件查找??-?返回数组中的第一个??
+?(instancetype)findWhereColoum:(NSString?*)coloum?equleToValue:(NSString?*)value;??
/**?通过条件查找数据
?*?这样可以进行分页查询?@"?WHERE?pk?>?5?limit?10"
?*/??
+?(NSArray?*)findByCriteria:(NSString?*)criteria;??
#pragma?mark?-?must?be?override?method??
/**
?*?创建表
?*?如果已经创建,返回YES
?*/??
+?(BOOL)createTable;??
/**?如果子类中有一些property不需要创建数据库字段,那么这个方法必须在子类中重写
?*/??
+?(NSArray?*)transients;??
//数据是否存在??
-?(BOOL?)isExsistObj;??
@end?
#import?"DBHelper.h"??
#define?dbTimeCount?@"recent_time"??
@implementation?DBBaseModel??
#pragma?mark?-?override?method??
+?(void)initialize??
{??
if?(self?!=?[DBBaseModel?self])?{??
[self?createTable];??
????}??
}??
-?(instancetype)init??
{??
self?=?[super?init];??
if?(self)?{??
NSDictionary?*dic?=?[self.class?getAllProperties];??
_columeNames?=?[[NSMutableArray?alloc]?initWithArray:[dic?objectForKey:@"name"]];??
_columeTypes?=?[[NSMutableArray?alloc]?initWithArray:[dic?objectForKey:@"type"]];??
????}??
return?self;??
}??
#pragma?mark?-?base?method??
/**
?*??获取该类的所有属性
?*/??
+?(NSDictionary?*)getPropertys??
{??
NSMutableArray?*proNames?=?[NSMutableArray?array];??
NSMutableArray?*proTypes?=?[NSMutableArray?array];??
NSArray?*theTransients?=?[[self?class]?transients];??
unsignedint?outCount,?i;??
objc_property_t?*properties?=?class_copyPropertyList([self?class],?&outCount);??
for?(i?=?0;?i?<?outCount;?i++)?{??
????????objc_property_t?property?=?properties[i];??
//获取属性名??
NSString?*propertyName?=?[NSString?stringWithCString:property_getName(property)?encoding:NSUTF8StringEncoding];??
if?([theTransients?containsObject:propertyName])?{??
continue;??
????????}??
[proNames?addObject:propertyName];??
//获取属性类型等参数??
NSString?*propertyType?=?[NSString?stringWithCString:?property_getAttributes(property)?encoding:NSUTF8StringEncoding];??
/*
?????????c?char?????????C?unsigned?char
?????????i?int??????????I?unsigned?int
?????????l?long?????????L?unsigned?long
?????????s?short????????S?unsigned?short
?????????d?double???????D?unsigned?double
?????????f?float????????F?unsigned?float
?????????q?long?long????Q?unsigned?long?long
?????????B?BOOL
?????????@?对象类型?//指针?对象类型?如NSString?是@“NSString”
?????????64位下long?和long?long?都是Tq
?????????SQLite?默认支持五种数据类型TEXT、INTEGER、REAL、BLOB、NULL
?????????*/??
if?([propertyType?hasPrefix:@"T@"])?{??
[proTypes?addObject:SQLTEXT];??
}else?if?([propertyType?hasPrefix:@"Ti"]||[propertyType?hasPrefix:@"TI"]||[propertyType?hasPrefix:@"Ts"]||[propertyType?hasPrefix:@"TS"]||[propertyType?hasPrefix:@"TB"])?{??
[proTypes?addObject:SQLINTEGER];??
}else?{??
[proTypes?addObject:SQLREAL];??
????????}??
????}??
????free(properties);??
return?[NSDictionary?dictionaryWithObjectsAndKeys:proNames,@"name",proTypes,@"type",nil];??
}??
/**?获取所有属性,包含主键pk?*/??
+?(NSDictionary?*)getAllProperties??
{??
NSDictionary?*dict?=?[self.class?getPropertys];??
NSMutableArray?*proNames?=?[NSMutableArray?array];??
NSMutableArray?*proTypes?=?[NSMutableArray?array];??
[proNames?addObject:primaryId];??
[proTypes?addObject:[NSString?stringWithFormat:@"%@?%@",SQLINTEGER,PrimaryKey]];??
[proNames?addObjectsFromArray:[dict?objectForKey:@"name"]];??
[proTypes?addObjectsFromArray:[dict?objectForKey:@"type"]];??
return?[NSDictionary?dictionaryWithObjectsAndKeys:proNames,@"name",proTypes,@"type",nil];??
}??
/**?数据库中是否存在表?*/??
+?(BOOL)isExistInTable??
{??
__blockBOOL?res?=?NO;??
DBHelper?*dbHelper?=?[DBHelper?sharedHelper];??
[dbHelper.dbQueue?inDatabase:^(FMDatabase?*db)?{??
NSString?*tableName?=?NSStringFromClass(self.class);??
res?=?[db?tableExists:tableName];??
????}];??
return?res;??
}??
+?(NSArray?*)getColumns??
{??
DBHelper?*dbHelper?=?[DBHelper?sharedHelper];??
NSMutableArray?*columns?=?[NSMutableArray?array];??
[dbHelper.dbQueue?inDatabase:^(FMDatabase?*db)?{??
NSString?*tableName?=?NSStringFromClass(self.class);??
FMResultSet?*resultSet?=?[db?getTableSchema:tableName];??
while?([resultSet?next])?{??
NSString?*column?=?[resultSet?stringForColumn:@"name"];??
[columns?addObject:column];??
????????}??
????}];??
return?[columns?copy];??
}??
/**
?*?创建表
?*?如果已经创建,返回YES
?*/??
+?(BOOL)createTable??
{??
FMDatabase?*db?=?[FMDatabase?databaseWithPath:[DBHelper?dbPath]];??
if?(![db?open])?{??
NSLog(@"数据库打开失败!");??
return?NO;??
????}??
NSString?*tableName?=?NSStringFromClass(self.class);??
NSString?*columeAndType?=?[self.class?getColumeAndTypeString];??
NSString?*sql?=?[NSString?stringWithFormat:@"CREATE?TABLE?IF?NOT?EXISTS?%@(%@);",tableName,columeAndType];??
if?(![db?executeUpdate:sql])?{??
return?NO;??
????}??
NSMutableArray?*columns?=?[NSMutableArray?array];??
FMResultSet?*resultSet?=?[db?getTableSchema:tableName];??
while?([resultSet?next])?{??
NSString?*column?=?[resultSet?stringForColumn:@"name"];??
[columns?addObject:column];??
????}??
NSDictionary?*dict?=?[self.class?getAllProperties];??
NSArray?*properties?=?[dict?objectForKey:@"name"];??
NSPredicate?*filterPredicate?=?[NSPredicate?predicateWithFormat:@"NOT?(SELF?IN?%@)",columns];??
//过滤数组??
NSArray?*resultArray?=?[properties?filteredArrayUsingPredicate:filterPredicate];??
for?(NSString?*column?in?resultArray)?{??
NSUInteger?index?=?[properties?indexOfObject:column];??
NSString?*proType?=?[[dict?objectForKey:@"type"]?objectAtIndex:index];??
NSString?*fieldSql?=?[NSString?stringWithFormat:@"%@?%@",column,proType];??
NSString?*sql?=?[NSString?stringWithFormat:@"ALTER?TABLE?%@?ADD?COLUMN?%@?",NSStringFromClass(self.class),fieldSql];??
if?(![db?executeUpdate:sql])?{??
return?NO;??
????????}??
????}??
[db?close];??
return?YES;??
}??
//数据是否存在??
-?(BOOL?)isExsistObj{??
id?otherPaimaryValue?=?[self?valueForKey:_keyWord];??
DBHelper?*dbHelper?=?[DBHelper?sharedHelper];??
__blockBOOL?isExist?=?NO;??
__blockDBBaseModel?*WeakSelf?=?self;??
[dbHelper.dbQueue?inDatabase:^(FMDatabase?*db)?{??
NSString?*tableName?=?NSStringFromClass(self.class);??
NSString?*sql?=?[NSString?stringWithFormat:@"SELECT?*?FROM?%@?WHERE?%@?=?'%@'",tableName,WeakSelf.keyWord,otherPaimaryValue];??
FMResultSet?*aResult?=?[db?executeQuery:sql];??
if([aResult?next]){??
isExist?=YES;??
}else{??
isExist?=NO;??
????????}??
[aResult?close];??
????}];??
return?isExist;??
}??
-?(BOOL)saveOrUpdate??
{??
BOOL?isExsist?=?[self?isExsistObj];??
if?(isExsist?)?{??
return??[self?update];??
}else{??
return?[self?save];??
????}??
}??
-?(BOOL)save??
{??
//保存修改时间??
NSTimeInterval?time?=?[[NSDate?date]timeIntervalSince1970];??
NSString?*str?=?[NSString?stringWithFormat:@"%.0f",time];??
NSString?*tableName?=?NSStringFromClass(self.class);??
NSMutableString?*keyString?=?[NSMutableString?string];??
NSMutableString?*valueString?=?[NSMutableString?string];??
NSMutableArray?*insertValues?=?[NSMutableArray??array];??
for?(int?i?=?0;?i?<?self.columeNames.count;?i++)?{??
NSString?*proname?=?[self.columeNames?objectAtIndex:i];??
if?([proname?isEqualToString:primaryId])?{??
continue;??
????????}??
[keyString?appendFormat:@"%@,",?proname];??
[valueString?appendString:@"?,"];??
id?value;??
if?([proname?isEqualToString:dbTimeCount])?{??
????????????value?=?str;??
}else{??
value?=?[self?valueForKey:proname];??
????????}??
if?(!value)?{??
value?=@"";??
????????}??
[insertValues?addObject:value];??
????}??
[keyString?deleteCharactersInRange:NSMakeRange(keyString.length?-?1,?1)];??
[valueString?deleteCharactersInRange:NSMakeRange(valueString.length?-?1,?1)];??
DBHelper?*dbHelper?=?[DBHelper?sharedHelper];??
__blockBOOL?res?=?NO;??
[dbHelper.dbQueue?inDatabase:^(FMDatabase?*db)?{??
NSString?*sql?=?[NSString?stringWithFormat:@"INSERT?INTO?%@(%@)?VALUES?(%@);",?tableName,?keyString,?valueString];??
res?=?[db?executeUpdate:sql?withArgumentsInArray:insertValues];??
self.pk?=?res?[NSNumber?numberWithLongLong:db.lastInsertRowId].intValue:0;??
NSLog(res?@"插入成功":@"插入失败");??
????}];??
return?res;??
}??
/**?批量保存用户对象?*/??
+?(BOOL)saveObjects:(NSArray?*)array??
{??
//判断是否是JKBaseModel的子类??
for?(DBBaseModel?*model?in?array)?{??
if?(![model?isKindOfClass:[DBBaseModel?class]])?{??
return?NO;??
????????}??
????}??
__blockBOOL?res?=?YES;??
DBHelper?*dbHelper?=?[DBHelper?sharedHelper];??
//?如果要支持事务??
[dbHelper.dbQueue?inTransaction:^(FMDatabase?*db,?BOOLBOOL?*rollback)?{??
for?(DBBaseModel?*model?in?array)?{??
//保存修改时间??
NSTimeInterval?time?=?[[NSDate?date]timeIntervalSince1970];??
NSString?*str?=?[NSString?stringWithFormat:@"%.0f",time];??
NSString?*tableName?=?NSStringFromClass(model.class);??
NSMutableString?*keyString?=?[NSMutableString?string];??
NSMutableString?*valueString?=?[NSMutableString?string];??
NSMutableArray?*insertValues?=?[NSMutableArray??array];??
for?(int?i?=?0;?i?<?model.columeNames.count;?i++)?{??
NSString?*proname?=?[model.columeNames?objectAtIndex:i];??
if?([proname?isEqualToString:primaryId])?{??
continue;??
????????????????}??
[keyString?appendFormat:@"%@,",?proname];??
[valueString?appendString:@"?,"];??
id?value;??
if?([proname?isEqualToString:dbTimeCount])?{??
????????????????????value?=?str;??
}else{??
value?=?[model?valueForKey:proname];??
????????????????}??
if?(!value)?{??
value?=@"";??
????????????????}??
[insertValues?addObject:value];??
????????????}??
[keyString?deleteCharactersInRange:NSMakeRange(keyString.length?-?1,?1)];??
[valueString?deleteCharactersInRange:NSMakeRange(valueString.length?-?1,?1)];??
NSString?*sql?=?[NSString?stringWithFormat:@"INSERT?INTO?%@(%@)?VALUES?(%@);",?tableName,?keyString,?valueString];??
BOOL?flag?=?[db?executeUpdate:sql?withArgumentsInArray:insertValues];??
model.pk?=?flag?[NSNumber?numberWithLongLong:db.lastInsertRowId].intValue:0;??
NSLog(flag?@"插入成功":@"插入失败");??
if?(!flag)?{??
res?=NO;??
*rollback?=YES;??
return;??
????????????}??
????????}??
????}];??
return?res;??
}??
/**?更新单个对象?*/??
-?(BOOL)update??
{??
//设置更新时间??
NSTimeInterval?time?=?[[NSDate?date]timeIntervalSince1970];??
NSString?*str?=?[NSString?stringWithFormat:@"%.0f",time];??
DBHelper?*dbHelper?=?[DBHelper?sharedHelper];??
__blockBOOL?res?=?NO;??
[dbHelper.dbQueue?inDatabase:^(FMDatabase?*db)?{??
NSString?*tableName?=?NSStringFromClass(self.class);??
id?primaryValue?=?[self?valueForKey:self.keyWord];??
NSMutableString?*keyString?=?[NSMutableString?string];??
NSMutableArray?*updateValues?=?[NSMutableArray??array];??
for?(int?i?=?0;?i?<?self.columeNames.count;?i++)?{??
NSString?*proname?=?[self.columeNames?objectAtIndex:i];??
if?([proname?isEqualToString:self.keyWord])?{??
continue;??
????????????}??
if([proname?isEqualToString:primaryId]){??
continue;??
????????????}??
[keyString?appendFormat:@"?%@=?,",?proname];??
id?value;??
if?([proname?isEqualToString:dbTimeCount])?{??
????????????????value?=?str;??
}else{??
value?=?[self?valueForKey:proname];??
????????????}??
if?(!value)?{??
value?=@"";??
????????????}??
[updateValues?addObject:value];??
????????}??
//删除最后那个逗号??
[keyString?deleteCharactersInRange:NSMakeRange(keyString.length?-?1,?1)];??
NSString?*sql?=?[NSString?stringWithFormat:@"UPDATE?%@?SET?%@?WHERE?%@?=??;",?tableName,?keyString,?self.keyWord];??
[updateValues?addObject:primaryValue];??
res?=?[db?executeUpdate:sql?withArgumentsInArray:updateValues];??
NSLog(res?@"更新成功":@"更新失败");??
????}];??
return?res;??
}??
/**?批量更新用户对象*/??
+?(BOOL)updateObjects:(NSArray?*)array??
{??
for?(DBBaseModel?*model?in?array)?{??
if?(![model?isKindOfClass:[DBBaseModel?class]])?{??
return?NO;??
????????}??
????}??
__blockBOOL?res?=?YES;??
DBHelper?*dbHelper?=?[DBHelper?sharedHelper];??
//?如果要支持事务??
[dbHelper.dbQueue?inTransaction:^(FMDatabase?*db,?BOOLBOOL?*rollback)?{??
for?(DBBaseModel?*model?in?array)?{??
NSTimeInterval?time?=?[[NSDate?date]timeIntervalSince1970];??
NSString?*str?=?[NSString?stringWithFormat:@"%.0f",time];??
NSString?*tableName?=?NSStringFromClass(model.class);??
id?primaryValue?=?[model?valueForKey:primaryId];??
if?(!primaryValue?||?primaryValue?<=?0)?{??
res?=NO;??
*rollback?=YES;??
return;??
????????????}??
NSMutableString?*keyString?=?[NSMutableString?string];??
NSMutableArray?*updateValues?=?[NSMutableArray??array];??
for?(int?i?=?0;?i?<?model.columeNames.count;?i++)?{??
NSString?*proname?=?[model.columeNames?objectAtIndex:i];??
if?([proname?isEqualToString:primaryId])?{??
continue;??
????????????????}??
[keyString?appendFormat:@"?%@=?,",?proname];??
id?value;??
if?([proname?isEqualToString:dbTimeCount])?{??
????????????????????value?=?str;??
}else{??
value?=?[model?valueForKey:proname];??
????????????????}??
if?(!value)?{??
value?=@"";??
????????????????}??
[updateValues?addObject:value];??
????????????}??
//删除最后那个逗号??
[keyString?deleteCharactersInRange:NSMakeRange(keyString.length?-?1,?1)];??
NSString?*sql?=?[NSString?stringWithFormat:@"UPDATE?%@?SET?%@?WHERE?%@=?;",?tableName,?keyString,?primaryId];??
[updateValues?addObject:primaryValue];??
BOOL?flag?=?[db?executeUpdate:sql?withArgumentsInArray:updateValues];??
NSLog(flag?@"更新成功":@"更新失败");??
if?(!flag)?{??
res?=NO;??
*rollback?=YES;??
return;??
????????????}??
????????}??
????}];??
return?res;??
}??
/**?删除单个对象?*/??
-?(BOOL)deleteObject??
{??
DBHelper?*dbHelper?=?[DBHelper?sharedHelper];??
__blockBOOL?res?=?NO;??
[dbHelper.dbQueue?inDatabase:^(FMDatabase?*db)?{??
NSString?*tableName?=?NSStringFromClass(self.class);??
id?primaryValue?=?[self?valueForKey:primaryId];??
if?(!primaryValue?||?primaryValue?<=?0)?{??
return?;??
????????}??
NSString?*sql?=?[NSString?stringWithFormat:@"DELETE?FROM?%@?WHERE?%@?=??",tableName,primaryId];??
res?=?[db?executeUpdate:sql?withArgumentsInArray:@[primaryValue]];??
NSLog(res?@"删除成功":@"删除失败");??
????}];??
return?res;??
}??
/**?批量删除用户对象?*/??
+?(BOOL)deleteObjects:(NSArray?*)array??
{??
for?(DBBaseModel?*model?in?array)?{??
if?(![model?isKindOfClass:[DBBaseModel?class]])?{??
return?NO;??
????????}??
????}??
__blockBOOL?res?=?YES;??
DBHelper?*dbHelper?=?[DBHelper?sharedHelper];??
//?如果要支持事务??
[dbHelper.dbQueue?inTransaction:^(FMDatabase?*db,?BOOLBOOL?*rollback)?{??
for?(DBBaseModel?*model?in?array)?{??
NSString?*tableName?=?NSStringFromClass(model.class);??
id?primaryValue?=?[model?valueForKey:primaryId];??
if?(!primaryValue?||?primaryValue?<=?0)?{??
return?;??
????????????}??
NSString?*sql?=?[NSString?stringWithFormat:@"DELETE?FROM?%@?WHERE?%@?=??",tableName,primaryId];??
BOOL?flag?=?[db?executeUpdate:sql?withArgumentsInArray:@[primaryValue]];??
NSLog(flag?@"删除成功":@"删除失败");??
if?(!flag)?{??
res?=NO;??
*rollback?=YES;??
return;??
????????????}??
????????}??
????}];??
return?res;??
}??
/**?通过条件删除数据?*/??
+?(BOOL)deleteObjectsByCriteria:(NSString?*)criteria??
{??
DBHelper?*dbHelper?=?[DBHelper?sharedHelper];??
__blockBOOL?res?=?NO;??
[dbHelper.dbQueue?inDatabase:^(FMDatabase?*db)?{??
NSString?*tableName?=?NSStringFromClass(self.class);??
NSString?*sql?=?[NSString?stringWithFormat:@"DELETE?FROM?%@?%@?",tableName,criteria];??
res?=?[db?executeUpdate:sql];??
NSLog(res?@"删除成功":@"删除失败");??
????}];??
return?res;??
}??
/**?清空表?*/??
+?(BOOL)clearTable??
{??
DBHelper?*dbHelper?=?[DBHelper?sharedHelper];??
__blockBOOL?res?=?NO;??
[dbHelper.dbQueue?inDatabase:^(FMDatabase?*db)?{??
NSString?*tableName?=?NSStringFromClass(self.class);??
NSString?*sql?=?[NSString?stringWithFormat:@"DELETE?FROM?%@",tableName];??
res?=?[db?executeUpdate:sql];??
NSLog(res?@"清空成功":@"清空失败");??
????}];??
return?res;??
}??
/**?查询全部数据?*/??
+?(NSArray?*)findAll??
{??
NSLog(@"db---%s",__func__);??
DBHelper?*dbHelper?=?[DBHelper?sharedHelper];??
NSMutableArray?*users?=?[NSMutableArray?array];??
[dbHelper.dbQueue?inDatabase:^(FMDatabase?*db)?{??
NSString?*tableName?=?NSStringFromClass(self.class);??
NSString?*sql?=?[NSString?stringWithFormat:@"SELECT?*?FROM?%@",tableName];??
FMResultSet?*resultSet?=?[db?executeQuery:sql];??
while?([resultSet?next])?{??
DBBaseModel?*model?=?[[self.class?alloc]?init];??
for?(int?i=0;?i<?model.columeNames.count;?i++)?{??
NSString?*columeName?=?[model.columeNames?objectAtIndex:i];??
NSString?*columeType?=?[model.columeTypes?objectAtIndex:i];??
if?([columeType?isEqualToString:SQLTEXT])?{??
[model?setValue:[resultSet?stringForColumn:columeName]?forKey:columeName];??
}else?{??
[model?setValue:[NSNumber?numberWithLongLong:[resultSet?longLongIntForColumn:columeName]]?forKey:columeName];??
????????????????}??
????????????}??
[users?addObject:model];??
????????????FMDBRelease(model);??
????????}??
????}];??
return?users;??
}??
/**?查找某条数据?*/??
+?(instancetype)findFirstByCriteria:(NSString?*)criteria??
{??
NSArray?*results?=?[self.class?findByCriteria:criteria];??
if?(results.count?<?1)?{??
return?nil;??
????}??
return?[results?firstObject];??
}??
+?(instancetype)findByPK:(int)inPk??
{??
NSString?*condition?=?[NSString?stringWithFormat:@"WHERE?%@=%d",primaryId,inPk];??
return?[self?findFirstByCriteria:condition];??
}??
/**?通过条件查找数据?*/??
+?(NSArray?*)findByCriteria:(NSString?*)criteria??
{??
DBHelper?*dbHelper?=?[DBHelper?sharedHelper];??
NSMutableArray?*users?=?[NSMutableArray?array];??
[dbHelper.dbQueue?inDatabase:^(FMDatabase?*db)?{??
NSString?*tableName?=?NSStringFromClass(self.class);??
NSString?*sql?=?[NSString?stringWithFormat:@"SELECT?*?FROM?%@??%@",tableName,criteria];??
FMResultSet?*resultSet?=?[db?executeQuery:sql];??
while?([resultSet?next])?{??
DBBaseModel?*model?=?[[self.class?alloc]?init];??
for?(int?i=0;?i<?model.columeNames.count;?i++)?{??
NSString?*columeName?=?[model.columeNames?objectAtIndex:i];??
NSString?*columeType?=?[model.columeTypes?objectAtIndex:i];??
if?([columeType?isEqualToString:SQLTEXT])?{??
[model?setValue:[resultSet?stringForColumn:columeName]?forKey:columeName];??
}else?{??
[model?setValue:[NSNumber?numberWithLongLong:[resultSet?longLongIntForColumn:columeName]]?forKey:columeName];??
????????????????}??
????????????}??
[users?addObject:model];??
????????????FMDBRelease(model);??
????????}??
????}];??
return?users;??
}??
//?值?为?通过?条件查找??-?返回数组中的第一个??
+?(instancetype)findWhereColoum:(NSString?*)coloum?equleToValue:(NSString?*)value{??
return?[[self?class]?findFirstByCriteria:[NSString?stringWithFormat:@"WHERE?%@='%@'",coloum,value]];??
}??
#pragma?mark?-?util?method??
+?(NSString?*)getColumeAndTypeString??
{??
NSMutableString*?pars?=?[NSMutableString?string];??
NSDictionary?*dict?=?[self.class?getAllProperties];??
NSMutableArray?*proNames?=?[dict?objectForKey:@"name"];??
NSMutableArray?*proTypes?=?[dict?objectForKey:@"type"];??
for?(int?i=0;?i<?proNames.count;?i++)?{??
[pars?appendFormat:@"%@?%@",[proNames?objectAtIndex:i],[proTypes?objectAtIndex:i]];??
if(i+1?!=?proNames.count)??
????????{??
[pars?appendString:@","];??
????????}??
????}??
return?pars;??
}??
-?(NSString?*)description??
{??
NSString?*result?=?@"";??
NSDictionary?*dict?=?[self.class?getAllProperties];??
NSMutableArray?*proNames?=?[dict?objectForKey:@"name"];??
for?(int?i?=?0;?i?<?proNames.count;?i++)?{??
NSString?*proName?=?[proNames?objectAtIndex:i];??
id??proValue?=?[self?valueForKey:proName];??
result?=?[result?stringByAppendingFormat:@"%@:%@\n",proName,proValue];??
????}??
return?result;??
}??
#pragma?mark?-?must?be?override?method??
/**?如果子类中有一些property不需要创建数据库字段,那么这个方法必须在子类中重写
?*/??
+?(NSArray?*)transients??
{??
return?@[];??
}??
@end??
DBHelper类
#import?"FMDB.h" ?
/**
?*??数据库管理工具
?*/??
@interface?DBHelper?:?NSObject??
@property(nonatomic,retain,readonly)FMDatabaseQueue?*dbQueue;??
/**
?*??获取数据库管理类单例
?*/??
+(DBHelper?*)sharedHelper;??
/**
?*??数据库文件沙盒地址
?*/??
+?(NSString?*)dbPath;??
@end??
#import?"DBHelper.h"??
@interface?DBHelper?()??
@property?(nonatomic,?retain)?FMDatabaseQueue?*dbQueue;??
@end??
@implementation?DBHelper??
+(DBHelper?*)sharedHelper{??
static?DBHelper?*instance?=?nil;??
static?dispatch_once_t?onceToken;??
if?(!instance)?{??
????????dispatch_once(&onceToken,?^{??
instance?=?[[super?allocWithZone:nil]init];??
????????});??
????}??
return?instance;??
}??
//lazy?load??
-(FMDatabaseQueue?*)dbQueue{??
if?(!_dbQueue)?{??
_dbQueue?=?[FMDatabaseQueue?databaseQueueWithPath:[[self?class]?dbPath]];??
????}??
return?_dbQueue;??
}??
//数据库地址??
+?(NSString?*)dbPath??
{??
NSString?*docsdir?=?[NSSearchPathForDirectoriesInDomains(?NSCachesDirectory,?NSUserDomainMask,?YES)?lastObject];??
NSFileManager?*filemanage?=?[NSFileManager?defaultManager];??
docsdir?=?[docsdir?stringByAppendingPathComponent:@"AppDataBase"];??
BOOL?isDir;??
BOOL?exit?=[filemanage?fileExistsAtPath:docsdir?isDirectory:&isDir];??
if?(!exit?||?!isDir)?{??
[filemanage?createDirectoryAtPath:docsdir?withIntermediateDirectories:YES?attributes:nil?error:nil];??
????}??
NSString?*dbpath?=?[docsdir?stringByAppendingPathComponent:@"TierTime.sqlite"];??
return?dbpath;??
}??
#pragma?--mark?保证单例不会被创建成新对象??
+(instancetype)alloc{??
NSAssert(0,?@"这是一个单例对象,请使用+(DBHelper?*)sharedHelper方法");??
return?nil;??
}??
+?(id)allocWithZone:(struct?_NSZone?*)zone??
{??
return?[DBHelper?sharedHelper];??
}??
-?(id)copyWithZone:(struct?_NSZone?*)zone??
{??
return?[DBHelper?sharedHelper];??
}??
@end??
使用示例:
PicCacheModel?*pic1?=?[[PicCacheModel?alloc]init];??
pic1.pic_name???????=?@"DefaultImage_0";??
pic1.pic_from_source?=?@"0";??
pic1.pic_path???????=?[NSString?stringWithFormat:@"%@.png",pic1.pic_name];??
pic1.pic_md5_str????=?[TRMD5?file_md5:MODEL_DEFAULT_SAVE_PATH(pic1.pic_path)];??
PicCacheModel?*pic2?=?[[PicCacheModel?alloc]init];??
pic2.pic_name???????=?@"DefaultImage_1";??
pic2.pic_from_source?=?@"0";??
pic2.pic_path???????=?[NSString?stringWithFormat:@"%@.png",pic2.pic_name];??
pic2.pic_md5_str????=?[TRMD5?file_md5:MODEL_DEFAULT_SAVE_PATH(pic2.pic_path)];??
PicCacheModel?*pic3?=?[[PicCacheModel?alloc]init];??
pic3.pic_name???????=?@"DefaultImage_2";??
pic3.pic_from_source?=?@"0";??
pic3.pic_path???????=?[NSString?stringWithFormat:@"%@.png",pic3.pic_name];??
pic3.pic_md5_str????=?[TRMD5?file_md5:MODEL_DEFAULT_SAVE_PATH(pic3.pic_path)];??
[pic1?saveOrUpdate];??
[pic2?saveOrUpdate];??
[pic3?saveOrUpdate];?
贴到这里,更多用法大家可以尝试一下