iOS如何優(yōu)雅的使用FMDB

//
//  WJDataBaseManager.h
//  wenjin
//
//  Created by Kevin on 2017/4/17.
//  Copyright ? 2017年 Hangzhou Chuanwoqi Internet Technology Co., Ltd. All rights reserved.
//

#import <Foundation/Foundation.h>

/**
 數(shù)據(jù)庫管理
 - (void)createTables 中使用model創(chuàng)建表
 */
@interface WJDataBaseManager : NSObject


/**
 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 在app啟動時初始化供屉。例如:[[WJDataBaseManager shareManager] registerTables:@[@"WJTestModel1",@"WJTestModel2"]];
 */
+ (instancetype)shareManager;


/**
 創(chuàng)建表(使用model名創(chuàng)建對應(yīng)表),model名 -> table名
 注意事項:一個model對應(yīng)一張表羡铲,因此一張表只會被創(chuàng)建一次忿族,model往后的修改不會被重新創(chuàng)建误堡,可使用新model名創(chuàng)建新的table.
 表的設(shè)計需慎重速挑,考慮app版本兼容性回铛,建議不要修改model派昧,而使用新的model脚祟。

 @param tables 存放model名稱的數(shù)組。
 */
- (void)registerTables:(NSArray <NSString*>*)tables;

/**
 *  插入數(shù)據(jù)
 *
 *  param model       模型
 *  param finishBlock 插入完成回調(diào)
 */
-(void)insert:(id)model FinishBlock:(void (^)(bool issuccess))finishBlock;
/**
 *  更新數(shù)據(jù)庫
 *
 *  param model 模型
 *  param where 條件
 *  param finishBlock 更新完成回調(diào)
 *
 *  return 是否成功
 */
-(void)update:(id)model Where:(NSString*)where FinishBlock:(void (^)(bool issuccess))finishBlock;
/**
 *  查詢數(shù)據(jù)庫
 *
 *  param model 模型
 *  param where 條件
 *  param order 排序
 *  param limit 限制行數(shù)
 *
 *  return 模型數(shù)組
 */
-(NSArray*)select:(id)model Where:(NSString*)where Order:(NSString*)order Limit:(NSString*)limit;

/**
 *  刪除
 *
 *  param model 模型
 *  param where 條件
 *
 *  return 刪除是否成功
 */
-(BOOL)delete:(id)model Where:(NSString*)where;

/**
 *  查詢表總記錄數(shù)
 *
 *  param model 模型
 *
 *  return 總數(shù)
 */
-(NSInteger)getCount:(id)model;
-(NSInteger)getCount:(id)model where:(NSString*)where;
-(NSInteger)getSum:(id)model Filed:(NSString*)filed where:(NSString*)where;
//  表是否存在
-(BOOL)isExit:(id)model;
//  刪除表數(shù)據(jù)
-(void)clearTable:(id)model;

@end
//
//  WJDataBaseManager.m
//  wenjin
//
//  Created by Kevin on 2017/4/17.
//  Copyright ? 2017年 Hangzhou Chuanwoqi Internet Technology Co., Ltd. All rights reserved.
//

#import "WJDataBaseManager.h"
#import <MJExtension/MJExtension.h>

#define WJ_DATA_BASE_NAME @"WJ_DATA_BASE_NAME.db"

@interface WJDataBaseManager ()

@property (nonatomic,strong) FMDatabase *db;
@property (nonatomic,strong) FMDatabaseQueue *queue;

@end

@implementation WJDataBaseManager

+(instancetype)shareManager{
    static WJDataBaseManager *instance = nil;
    static dispatch_once_t oneToken;
    dispatch_once(&oneToken, ^{
        instance = [[WJDataBaseManager alloc] init];
    });
    return instance;
}

- (instancetype)init{
    self = [super init];
    if (self) {
        [self createDB];
    }
    return self;
}

#pragma mark -
#pragma mark 創(chuàng)建數(shù)據(jù)庫
- (void)createDB{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentDirectory = [paths objectAtIndex:0];
    NSString *dbPath = [documentDirectory stringByAppendingPathComponent:WJ_DATA_BASE_NAME];
    _queue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
    _db = [FMDatabase databaseWithPath:dbPath] ;
    if (![_db open]) {
        NSLog(@"Could not open db.");
        return ;
    }
    NSLog(@"database path : %@",dbPath);
    // 創(chuàng)建表
    [self createTables];
}

- (void)registerTables:(NSArray *)tables{
    for (NSString *table in tables) {
        if(NSClassFromString(table)){
            [self createTableWithModel:NSClassFromString(table)];
        }
    }
}

- (void)createTables{
    
    //根據(jù)model創(chuàng)建表
//    [self createTableWithModel:[WJMyStocksModel class]];
    
    
    
}

-(void)removeDatabase{
    [_db close];
    // 直接刪除文件
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *dbPath = _db.databasePath;
    if ([fileManager fileExistsAtPath:dbPath]) {
        [fileManager removeItemAtPath:dbPath error:nil];
    }
}

-(void)dropTable:(id)model{
    NSString *table = NSStringFromClass([model class]);
    NSString *sql = [NSString stringWithFormat:@"DROP TABLE IF EXISTS %@",table];
    [_db executeUpdate:sql];
}

-(void)clearTable:(id)model{
    NSString *table = NSStringFromClass([model class]);
    NSString *sql = [NSString stringWithFormat:@"DELETE FROM %@",table];
    [_db executeUpdate:sql];
}

#pragma mark -
#pragma mark 數(shù)據(jù)庫操作

//  插入數(shù)據(jù)
-(void)insert:(id)model FinishBlock:(void (^)(bool issuccess))finishBlock{
    NSString *fileds = @"";
    NSArray *keys = [self propertyKeysWithClass:[model class]];
    
    NSString *values = @"";
    for (NSString *key in keys) {
        NSString* value = [NSString stringWithFormat:@"%@",[model valueForKey:key]];
        if ([value isEqualToString:@"(null)"] || !value) {
            value = @"";
        }
        if ([fileds isEqualToString:@""]) {
            fileds = [fileds stringByAppendingFormat:@"%@",key];
            values = [values stringByAppendingFormat:@"'%@'",value];
        }else{
            fileds = [fileds stringByAppendingFormat:@",%@",key];
            values = [values stringByAppendingFormat:@",'%@'",value];
        }
    }
    NSString *table = NSStringFromClass([model class]);
    NSString *sql = [[NSString alloc]
                     initWithFormat:@"INSERT INTO %@ (%@) Values(%@)",table,fileds,values];
    // 加入隊列
    [_queue inDatabase:^(FMDatabase *dbs){
        bool success = [_db executeUpdate:sql];
        if (finishBlock) {
            finishBlock(success);
        }
    }];
    
}

//  更新數(shù)據(jù)
-(void)update:(id)model Where:(NSString*)where FinishBlock:(void (^)(bool issuccess))finishBlock{
    
    NSString *fileds = @"";
    NSArray *keys = [self propertyKeysWithClass:[model class]];
    for (NSString *key in keys) {
        NSString* value = [NSString stringWithFormat:@"%@",[model valueForKey:key]];
        if (![value isEqualToString:@"(null)"] && value) {
            if ([fileds isEqualToString:@""]) {
                fileds = [fileds stringByAppendingFormat:@"%@='%@'",key,value];
            }else{
                fileds = [fileds stringByAppendingFormat:@",%@='%@'",key,value];
            }
        }
        
    }
    NSString *table = NSStringFromClass([model class]);
    NSString *sql = [[NSString alloc]
                     initWithFormat:@"UPDATE %@ SET %@",table,fileds];
    if (where) {
        sql = [sql stringByAppendingFormat:@" WHERE %@",where];
    }
    // 加入隊列
    [_queue inDatabase:^(FMDatabase *dbs){
        bool success = [_db executeUpdate:sql];
        if (finishBlock) {
            finishBlock(success);
        }
    }];
}

//  查詢
-(NSArray*)select:(id)model Where:(NSString*)where Order:(NSString*)order Limit:(NSString*)limit{
    NSString *table = NSStringFromClass([model class]);
    NSString *sql = [NSString stringWithFormat:@"SELECT * FROM %@",table];
    if (where) {
        sql = [sql stringByAppendingFormat:@" WHERE %@",where];
    }
    if (order) {
        sql = [sql stringByAppendingFormat:@" ORDER BY %@",order];
    }
    if (limit) {
        sql = [sql stringByAppendingFormat:@" LIMIT %@",limit];
    }
    NSMutableArray *array = [NSMutableArray new];
    FMResultSet *rs = [_db executeQuery:sql];
    while ([rs next]) {
        NSDictionary *dic = [rs resultDictionary];
        id m = [[model class] mj_objectWithKeyValues:dic];
        [array addObject:m];
        dic = nil;
        m = nil;
    }
    return array;
}


//  刪除
-(BOOL)delete:(id)model Where:(NSString*)where{
    NSString *table = NSStringFromClass([model class]);
    NSString *sql = [NSString stringWithFormat:@"DELETE FROM %@",table];
    if (where) {
        sql = [sql stringByAppendingFormat:@" WHERE %@",where];
    }
    
    BOOL success = [_db executeUpdate:sql];
    return success;
    
}

//  獲取表記錄總數(shù)
-(NSInteger)getCount:(id)model{
    NSString *table = NSStringFromClass([model class]);
    NSInteger count = 0;
    NSString *sqlStr = [NSString stringWithFormat:@"SELECT COUNT(*) FROM %@",table];
    count = [_db intForQuery:sqlStr];
    return count;
}

-(NSInteger)getCount:(id)model where:(NSString*)where{
    NSString *table = NSStringFromClass([model class]);
    NSInteger count = 0;
    NSString *sql = [NSString stringWithFormat:@"SELECT COUNT(*) FROM %@",table];
    if (where) {
        sql = [sql stringByAppendingFormat:@" WHERE %@",where];
    }
    count = [_db intForQuery:sql];
    return count;
}

-(NSInteger)getSum:(id)model Filed:(NSString*)filed where:(NSString*)where{
    NSString *table = NSStringFromClass([model class]);
    NSInteger count = 0;
    NSString *sql = [NSString stringWithFormat:@"SELECT SUM(%@) FROM %@",filed,table];
    if (where) {
        sql = [sql stringByAppendingFormat:@" WHERE %@",where];
    }
    count = [_db intForQuery:sql];
    return count;
}

//  通過模型創(chuàng)建表
-(void)createTableWithModel:(id)model{
    if (![self isExit:model]) {
        NSString *s = [self createSqlWithTableModel:[model class]];
        [_db executeUpdate:s];
    }
}

//  通過模型生成創(chuàng)建表語句
-(NSString*)createSqlWithTableModel:(id)model{
    NSArray *propertys = [self propertyKeysWithClass:[model class]];
    NSString *keys = @"";
    NSString *className = NSStringFromClass([model class]);
    NSString *sql = [NSString stringWithFormat:@"CREATE TABLE %@ (",className];
    for (NSString *key in propertys) {
        //  字符串
        if ([[key class] isSubclassOfClass:[NSString class]]) {
            keys = [keys stringByAppendingString:[NSString stringWithFormat:@"%@ text,",key]];
        }
        //  數(shù)字
        if ([[key class] isSubclassOfClass:[NSNumber class]]) {
            keys = [keys stringByAppendingString:[NSString stringWithFormat:@"%@ integer,",key]];
        }
    }
    if ([[keys substringFromIndex:keys.length-1] isEqualToString:@","]) {
        keys = [keys substringToIndex:keys.length-1];
    }
    sql = [sql stringByAppendingString:[NSString stringWithFormat:@"%@)",keys]];
    return sql;
}

//  表是否存在
-(BOOL)isExit:(id)model{
    NSString *table = NSStringFromClass([model class]);
    BOOL exit = NO;
    exit = [_db intForQuery:@"select count(*) as 'count' from sqlite_master where type ='table' and name = ?",table];
    return exit;
}

//  反射對象所有屬性
- (NSArray*)propertyKeysWithClass:(Class)classs
{
    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList(classs, &outCount);
    NSMutableArray *keys = [[NSMutableArray alloc] initWithCapacity:outCount];
    for (i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        NSString *propertyName = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
        [keys addObject:propertyName];
    }
    free(properties);
    return keys;
}

@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末凄诞,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子忍级,更是在濱河造成了極大的恐慌帆谍,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件轴咱,死亡現(xiàn)場離奇詭異汛蝙,居然都是意外死亡,警方通過查閱死者的電腦和手機朴肺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門窖剑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人戈稿,你說我怎么就攤上這事西土。” “怎么了鞍盗?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵需了,是天一觀的道長。 經(jīng)常有香客問我般甲,道長肋乍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任敷存,我火速辦了婚禮墓造,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己觅闽,他們只是感情好帝雇,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谱煤,像睡著了一般摊求。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上刘离,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天室叉,我揣著相機與錄音,去河邊找鬼硫惕。 笑死茧痕,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的恼除。 我是一名探鬼主播踪旷,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼豁辉!你這毒婦竟也來了令野?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤徽级,失蹤者是張志新(化名)和其女友劉穎气破,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體餐抢,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡现使,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了旷痕。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碳锈。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖欺抗,靈堂內(nèi)的尸體忽然破棺而出售碳,到底是詐尸還是另有隱情,我是刑警寧澤绞呈,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布团滥,位于F島的核電站,受9級特大地震影響报强,放射性物質(zhì)發(fā)生泄漏灸姊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一秉溉、第九天 我趴在偏房一處隱蔽的房頂上張望力惯。 院中可真熱鬧碗誉,春花似錦、人聲如沸父晶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽甲喝。三九已至尝苇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間埠胖,已是汗流浹背糠溜。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留直撤,地道東北人非竿。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像谋竖,于是被迫代替她去往敵國和親红柱。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容