FMDB简介:
是iOS平台的第三方数据库框架,将SQLite API以OC的方式进行封装,面向对象,使用便捷。
FMDatabase:一个FMDatabase对象就代表一个单独的SQLite数据库,用来执行SQL语句,进行增删查改操作。
FMResultSet:使用FMDatabase执行查询后的结果集。
FMDatabaseQueue:保证线程安全,可以在多线程中同时读写、执行多个查询或更新。
使用:
创建队列对象:
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"HWDownloadVideoCaches.sqlite"];
// 创建队列对象,内部会自动创建一个数据库, 并且自动打开
_dbQueue = [FMDatabaseQueue databaseQueueWithPath:path];
创表:下面代表创建一张名为t_videoCaches的数据表,包含3个字段,默认且自增的主键id字段、totalFileSize字段、url字段。如“url text”代表字段名字是url,类型是text,其中除主键外,类型可以不写,为了方便阅读及编程规范还是建议写上。
[_dbQueue inDatabase:^(FMDatabase *db) {
// 创表
BOOL result = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_videoCaches (id integer PRIMARY KEY AUTOINCREMENT, totalFileSize integer, url text)"];
if (result) {
NSLog(@"创建成功");
}else {
NSLog(@"创建失败");
}
}];
常用类型:
整数数据类型:integer、bigint、smallint、tinyint
浮点数据类型:float、double、real
字符型数据类型:char(n)、varchar(n)、text
二进制数据:blob
日期类型:date、time、datetime、timestamp
增加数据:这里有一点要注意,不要直接传入基础类型,如int,要封装成对象,不然会crash掉。
[_dbQueue inDatabase:^(FMDatabase *db) {
BOOL result = [db executeUpdate:@"INSERT INTO t_videoCaches (totalFileSize, url) VALUES (?, ?)", [NSNumber numberWithInteger:1000], @"https://blog.csdn.net/hero_wqb"];
if (result) {
NSLog(@"插入成功");
}else {
NSLog(@"插入失败");
}
}];
删除数据:下面代表通过url在t_videoCaches表中查找数据,并将其删除。
[_dbQueue inDatabase:^(FMDatabase *db) {
BOOL result = [db executeUpdate:@"DELETE FROM t_videoCaches WHERE url = ?", url];
if (result) {
NSLog(@"删除成功");
}else {
NSLog(@"删除失败");
}
}];
查找数据:
1)快速查找某一数据:下面代表在t_videoCaches表中,根据url查找数据对应的totalFileSize。对应有stringForColumn:、boolForColumn:、doubleForColumn:、dataForColumn:、objectForColumn:等方法。
NSInteger totalFileSize = [db intForQuery:@"SELECT totalFileSize FROM t_videoCaches WHERE url = ?", url];
2)根据查询条件,返回一个集合:下面代表查询所有数据。
[_dbQueue inDatabase:^(FMDatabase *db) {
FMResultSet *resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches"];
while ([resultSet next]) {
NSInteger totalFileSize = [resultSet intForColumn:@"totalFileSize"];
NSString *url = [resultSet stringForColumn:@"url"];
NSLog(@"totalFileSize:%ld, url:%@", totalFileSize, url);
}
}];
修改数据:
[_dbQueue inDatabase:^(FMDatabase *db) {
BOOL result = [db executeUpdate:@"UPDATE t_videoCaches SET totalFileSize = ? WHERE url = ?", [NSNumber numberWithInteger:2000], @"https://blog.csdn.net/hero_wqb"];
if (result) {
NSLog(@"修改成功");
}else {
NSLog(@"修改失败");
}
}];
一些常用的sql语句:
创表:(其中table为自定义表名称,若表已存在不会重复创建)
"CREATE TABLE IF NOT EXISTS table (id integer PRIMARY KEY AUTOINCREMENT, variableA integer, variableB text)"
插入数据:(?指代变量,需要我们传入)
"INSERT INTO table (variableA, variableB) VALUES (?, ?)"
删除数据:(通过变量A查找出数据并删除)
"DELETE FROM table WHERE variableA = ?"
查找数据:
通过变量A查寻变量B的值:
"SELECT variableB FROM table WHERE variableA = ?"
查找整张表全部数据:(根据主键自增的顺序返回)
"SELECT * FROM table"
通过变量A查找数据:(根据主键自增的顺序返回)
"SELECT * FROM table WHERE variableA = ?"
查找变量A不满足某条件的数据:(根据主键自增的顺序返回)
"SELECT * FROM table WHERE variableA != ?"
通过变量A查找数据:(根据变量B由大到小的顺序返回,desc:倒序,asc:正序)
"SELECT * FROM table WHERE variableA = ? order by variableB desc"
通过变量A查找数据:(根据变量B由小到大的顺序返回第一条,limit 0,1:从第0个坐标开始,取1条数据)
"SELECT * FROM table WHERE variableA = ? order by variableB asc limit 0,1"
修改数据:(通过变量A查询数据,修改其变量B的值)
"UPDATE table SET variableB = ? WHERE variableA = ?"
封装了一个单例,下面贴上代码:
.h文件:#import
typedef NS_OPTIONS(NSUInteger, HWDBUpdateOption) {
HWDBUpdateOptionState = 1 << 0, // 更新状态
HWDBUpdateOptionLastStateTime = 1 << 1, // 更新状态最后改变的时间
HWDBUpdateOptionResumeData = 1 << 2, // 更新下载的数据
HWDBUpdateOptionProgressData = 1 << 3, // 更新进度数据
HWDBUpdateOptionAllParam = 1 << 4 // 更新全部数据
};
@interface HWDataBaseManager : NSObject
// 获取单例
+ (instancetype)shareManager;
// 插入数据
- (void)insertModel:(HWDownloadModel *)model;
// 获取数据
- (HWDownloadModel *)getModelWithUrl:(NSString *)url; // 根据url获取数据
- (HWDownloadModel *)getWaitingModel; // 获取第一条等待的数据
- (HWDownloadModel *)getLastDownloadingModel; // 获取最后一条正在下载的数据
- (NSArray *)getAllCacheData; // 获取所有数据
- (NSArray *)getAllDownloadingData; // 根据lastStateTime倒叙获取所有正在下载的数据
- (NSArray *)getAllDownloadedData; // 获取所有下载完成的数据
- (NSArray *)getAllUnDownloadedData; // 获取所有未下载完成的数据(包含正在下载、等待、暂停、错误)
- (NSArray *)getAllWaitingData; // 获取所有等待下载的数据
// 更新数据
- (void)updateWithModel:(HWDownloadModel *)model option:(HWDBUpdateOption)option;
// 删除数据
- (void)deleteModelWithUrl:(NSString *)url;
@end
.m文件:
#import "HWDataBaseManager.h"
typedef NS_ENUM(NSInteger, HWDBGetDateOption) {
HWDBGetDateOptionAllCacheData = 0, // 所有缓存数据
HWDBGetDateOptionAllDownloadingData, // 所有正在下载的数据
HWDBGetDateOptionAllDownloadedData, // 所有下载完成的数据
HWDBGetDateOptionAllUnDownloadedData, // 所有未下载完成的数据
HWDBGetDateOptionAllWaitingData, // 所有等待下载的数据
HWDBGetDateOptionModelWithUrl, // 通过url获取单条数据
HWDBGetDateOptionWaitingModel, // 第一条等待的数据
HWDBGetDateOptionLastDownloadingModel, // 最后一条正在下载的数据
};
@interface HWDataBaseManager ()
@property (nonatomic, strong) FMDatabaseQueue *dbQueue;
@end
@implementation HWDataBaseManager
+ (instancetype)shareManager
{
static HWDataBaseManager *manager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[self alloc] init];
});
return manager;
}
- (instancetype)init
{
if (self = [super init]) {
[self creatVideoCachesTable];
}
return self;
}
// 创表
- (void)creatVideoCachesTable
{
// 数据库文件路径
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"HWDownloadVideoCaches.sqlite"];
// 创建队列对象,内部会自动创建一个数据库, 并且自动打开
_dbQueue = [FMDatabaseQueue databaseQueueWithPath:path];
[_dbQueue inDatabase:^(FMDatabase *db) {
// 创表
BOOL result = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_videoCaches (id integer PRIMARY KEY AUTOINCREMENT, vid text, fileName text, url text, resumeData blob, totalFileSize integer, tmpFileSize integer, state integer, progress float, lastSpeedTime integer, intervalFileSize integer, lastStateTime integer)"];
if (result) {
// HWLog(@"视频缓存数据表创建成功");
}else {
HWLog(@"视频缓存数据表创建失败");
}
}];
}
// 插入数据
- (void)insertModel:(HWDownloadModel *)model
{
[_dbQueue inDatabase:^(FMDatabase *db) {
BOOL result = [db executeUpdate:@"INSERT INTO t_videoCaches (vid, fileName, url, resumeData, totalFileSize, tmpFileSize, state, progress, lastSpeedTime, intervalFileSize, lastStateTime) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", model.vid, model.fileName, model.url, model.resumeData, [NSNumber numberWithInteger:model.totalFileSize], [NSNumber numberWithInteger:model.tmpFileSize], [NSNumber numberWithInteger:model.state], [NSNumber numberWithFloat:model.progress], [NSNumber numberWithInteger:0], [NSNumber numberWithInteger:0], [NSNumber numberWithInteger:0]];
if (result) {
// HWLog(@"插入成功:%@", model.fileName);
}else {
HWLog(@"插入失败:%@", model.fileName);
}
}];
}
// 获取单条数据
- (HWDownloadModel *)getModelWithUrl:(NSString *)url
{
return [self getModelWithOption:HWDBGetDateOptionModelWithUrl url:url];
}
// 获取第一条等待的数据
- (HWDownloadModel *)getWaitingModel
{
return [self getModelWithOption:HWDBGetDateOptionWaitingModel url:nil];
}
// 获取最后一条正在下载的数据
- (HWDownloadModel *)getLastDownloadingModel
{
return [self getModelWithOption:HWDBGetDateOptionLastDownloadingModel url:nil];
}
// 获取所有数据
- (NSArray *)getAllCacheData
{
return [self getDateWithOption:HWDBGetDateOptionAllCacheData];
}
// 根据lastStateTime倒叙获取所有正在下载的数据
- (NSArray *)getAllDownloadingData
{
return [self getDateWithOption:HWDBGetDateOptionAllDownloadingData];
}
// 获取所有下载完成的数据
- (NSArray *)getAllDownloadedData
{
return [self getDateWithOption:HWDBGetDateOptionAllDownloadedData];
}
// 获取所有未下载完成的数据
- (NSArray *)getAllUnDownloadedData
{
return [self getDateWithOption:HWDBGetDateOptionAllUnDownloadedData];
}
// 获取所有等待下载的数据
- (NSArray *)getAllWaitingData
{
return [self getDateWithOption:HWDBGetDateOptionAllWaitingData];
}
// 获取单条数据
- (HWDownloadModel *)getModelWithOption:(HWDBGetDateOption)option url:(NSString *)url
{
__block HWDownloadModel *model = nil;
[_dbQueue inDatabase:^(FMDatabase *db) {
FMResultSet *resultSet;
switch (option) {
case HWDBGetDateOptionModelWithUrl:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE url = ?", url];
break;
case HWDBGetDateOptionWaitingModel:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state = ? order by lastStateTime asc limit 0,1", [NSNumber numberWithInteger:HWDownloadStateWaiting]];
break;
case HWDBGetDateOptionLastDownloadingModel:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state = ? order by lastStateTime desc limit 0,1", [NSNumber numberWithInteger:HWDownloadStateDownloading]];
break;
default:
break;
}
while ([resultSet next]) {
model = [[HWDownloadModel alloc] initWithFMResultSet:resultSet];
}
}];
return model;
}
// 获取数据集合
- (NSArray *)getDateWithOption:(HWDBGetDateOption)option
{
__block NSArray *array = nil;
[_dbQueue inDatabase:^(FMDatabase *db) {
FMResultSet *resultSet;
switch (option) {
case HWDBGetDateOptionAllCacheData:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches"];
break;
case HWDBGetDateOptionAllDownloadingData:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state = ? order by lastStateTime desc", [NSNumber numberWithInteger:HWDownloadStateDownloading]];
break;
case HWDBGetDateOptionAllDownloadedData:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state = ?", [NSNumber numberWithInteger:HWDownloadStateFinish]];
break;
case HWDBGetDateOptionAllUnDownloadedData:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state != ?", [NSNumber numberWithInteger:HWDownloadStateFinish]];
break;
case HWDBGetDateOptionAllWaitingData:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state = ?", [NSNumber numberWithInteger:HWDownloadStateWaiting]];
break;
default:
break;
}
NSMutableArray *tmpArr = [NSMutableArray array];
while ([resultSet next]) {
[tmpArr addObject:[[HWDownloadModel alloc] initWithFMResultSet:resultSet]];
}
array = tmpArr;
}];
return array;
}
// 更新数据
- (void)updateWithModel:(HWDownloadModel *)model option:(HWDBUpdateOption)option
{
[_dbQueue inDatabase:^(FMDatabase *db) {
if (option & HWDBUpdateOptionState) {
[self postStateChangeNotificationWithFMDatabase:db model:model];
[db executeUpdate:@"UPDATE t_videoCaches SET state = ? WHERE url = ?", [NSNumber numberWithInteger:model.state], model.url];
}
if (option & HWDBUpdateOptionLastStateTime) {
[db executeUpdate:@"UPDATE t_videoCaches SET lastStateTime = ? WHERE url = ?", [NSNumber numberWithInteger:[HWToolBox getTimeStampWithDate:[NSDate date]]], model.url];
}
if (option & HWDBUpdateOptionResumeData) {
[db executeUpdate:@"UPDATE t_videoCaches SET resumeData = ? WHERE url = ?", model.resumeData, model.url];
}
if (option & HWDBUpdateOptionProgressData) {
[db executeUpdate:@"UPDATE t_videoCaches SET tmpFileSize = ?, totalFileSize = ?, progress = ?, lastSpeedTime = ?, intervalFileSize = ? WHERE url = ?", [NSNumber numberWithInteger:model.tmpFileSize], [NSNumber numberWithFloat:model.totalFileSize], [NSNumber numberWithFloat:model.progress], [NSNumber numberWithInteger:model.lastSpeedTime], [NSNumber numberWithInteger:model.intervalFileSize], model.url];
}
if (option & HWDBUpdateOptionAllParam) {
[self postStateChangeNotificationWithFMDatabase:db model:model];
[db executeUpdate:@"UPDATE t_videoCaches SET resumeData = ?, totalFileSize = ?, tmpFileSize = ?, progress = ?, state = ?, lastSpeedTime = ?, intervalFileSize = ?, lastStateTime = ? WHERE url = ?", model.resumeData, [NSNumber numberWithInteger:model.totalFileSize], [NSNumber numberWithInteger:model.tmpFileSize], [NSNumber numberWithFloat:model.progress], [NSNumber numberWithInteger:model.state], [NSNumber numberWithInteger:model.lastSpeedTime], [NSNumber numberWithInteger:model.intervalFileSize], [NSNumber numberWithInteger:[HWToolBox getTimeStampWithDate:[NSDate date]]], model.url];
}
}];
}
// 状态变更通知
- (void)postStateChangeNotificationWithFMDatabase:(FMDatabase *)db model:(HWDownloadModel *)model
{
// 原状态
NSInteger oldState = [db intForQuery:@"SELECT state FROM t_videoCaches WHERE url = ?", model.url];
if (oldState != model.state) {
// 状态变更通知
[[NSNotificationCenter defaultCenter] postNotificationName:HWDownloadStateChangeNotification object:model];
}
}
// 删除数据
- (void)deleteModelWithUrl:(NSString *)url
{
[_dbQueue inDatabase:^(FMDatabase *db) {
BOOL result = [db executeUpdate:@"DELETE FROM t_videoCaches WHERE url = ?", url];
if (result) {
// HWLog(@"删除成功:%@", url);
}else {
HWLog(@"删除失败:%@", url);
}
}];
}
@end
Demo下载链接:https://github.com/HeroWqb/HWDownloadDemo
写博客的初心是希望大家共同交流成长,博主水平有限难免有偏颇之处,欢迎批评指正。