iOS FMDB数据库框架使用 —— HERO博客

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

写博客的初心是希望大家共同交流成长,博主水平有限难免有偏颇之处,欢迎批评指正。

你可能感兴趣的:(iOS,Objective-C技术分享)