FMDB使用

框架地址:[https://github.com/ccgus/fmdb]

  • 下載框架


    Snip20160912_6.png
  • 首先要明白框架中幾個(gè)重要的類(lèi)

    • FMDatabase 代表一個(gè)數(shù)據(jù)庫(kù) 并且可以使用它執(zhí)行sqlite語(yǔ)句
    • FMDatabaseQueue 是線程安全的存儲(chǔ)跟讀取數(shù)據(jù) 這里有一個(gè)概念---事物
    • FMResultSet 結(jié)果集 從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù)的集合
  • 使用之前會(huì)發(fā)現(xiàn)編譯報(bào)錯(cuò),需要先在Build Phases->Link Binary With Libraries->導(dǎo)入libsqlite3.tbd 再次編譯就??

FMDatabase

  • 首先我們我們不考慮線程安全下使用FMDatabase來(lái)創(chuàng)建數(shù)據(jù)庫(kù)實(shí)現(xiàn)離線緩存
    • 導(dǎo)入#import "FMDB.h"
// 1.獲得數(shù)據(jù)庫(kù)路徑
     NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"daba.sqlist"];
    // 2.創(chuàng)建數(shù)據(jù)對(duì)象
    FMDatabase *dataBase = [FMDatabase databaseWithPath:path];
    
    // 3.打開(kāi)數(shù)據(jù)庫(kù)的時(shí)候首先判斷當(dāng)前數(shù)據(jù)庫(kù)是否存在, 如果不存儲(chǔ)在就創(chuàng)建一個(gè)并打開(kāi), 如果存儲(chǔ)在那么就不創(chuàng)建直接打開(kāi)
    BOOL isSuccess = [dataBase open];
    if (!isSuccess) {
        NSLog(@"打開(kāi)數(shù)據(jù)庫(kù)失敗");
    }else{
        NSLog(@"打開(kāi)數(shù)據(jù)庫(kù)成功");
    
    }
}
  • 創(chuàng)建好數(shù)據(jù)庫(kù)之后,接下來(lái)就是根據(jù)我們的需求在數(shù)據(jù)庫(kù)中中創(chuàng)建表了,一個(gè)數(shù)據(jù)庫(kù)可以創(chuàng)建多張表, 一張表包含多個(gè)字段,也就是對(duì)應(yīng)表的column, 表是有row跟column構(gòu)成, 有點(diǎn)類(lèi)似Excle表

  • 細(xì)節(jié)不多說(shuō) 創(chuàng)建一個(gè)完整的字段表

// 數(shù)據(jù)庫(kù)前提是open狀態(tài)
    /**
     * PRIMARY KEY 主鍵
     * AUTOINCREMENT 自動(dòng)增量
     * UNIQUE 唯一
     * DEFAULT 默認(rèn)值
     *  @param INTEGER 整型
     *  @param TEXT    文本
     *  @param REAL    浮點(diǎn)型
     *  @param
     *  @param BLOB    二進(jìn)制
     */
    BOOL isSuccess = [dataBase executeUpdate:@"CREATE TABLE IF NOT EXIST t_table (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, age INTEGER  NOT NULL UNIQUE DEFAULT 0, score REAL NOT NULL unique, data BLOB);"];
    
    if (!isSuccess) {
        NSLog(@"創(chuàng)建表成功");
    }else{
        NSLog(@"創(chuàng)建表失敗");
        
    }
  • 表創(chuàng)建完成了,接下來(lái)就是我們利用FMDatabase對(duì)象要插入數(shù)據(jù)了, 這里我們了解一下插入數(shù)據(jù)的常見(jiàn)3中寫(xiě)法
    /**此種方式后面拼接的參數(shù)必須為對(duì)象 不可以為int double等基本數(shù)據(jù)類(lèi)型*/
    [dataBase executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
    /**此種方式后面拼接的參數(shù)可以為int double等基本數(shù)據(jù)類(lèi)型 因?yàn)槭鞘褂玫恼嘉环?/
    [dataBase executeUpdateWithFormat:@"insert into t_table(name, age, score, data) values(%@, %d , %f, %@)", @"jake", 12, 91.0, [NSData data]];
    /**此種方式后面拼接的參數(shù)必須為對(duì)象 不可以為int double等基本數(shù)據(jù)類(lèi)型 將對(duì)象依次防近視數(shù)組*/
    [dataBase executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)" withArgumentsInArray:@[@12, @91.0, [NSData data]]];

-注意 當(dāng)我們存儲(chǔ)表中BLOB 對(duì)應(yīng)的字段如果為字典的時(shí)候,這個(gè)時(shí)候我們不應(yīng)該把字典往里存,應(yīng)當(dāng)使用[NSKeyedArchiver archivedDataWithRootObject:<#(nonnull id)#>] 將字典轉(zhuǎn)換成NSData類(lèi)型, 這樣當(dāng)我們?nèi)〕鰯?shù)據(jù)的時(shí)候取出的是NSData類(lèi)型,再將NSData類(lèi)型數(shù)據(jù)通過(guò)[NSKeyedUnarchiver unarchiveObjectWithData:<#(nonnull NSData *)#>];反歸檔得到就是字典,如果直接存字典,從數(shù)據(jù)數(shù)據(jù)庫(kù)中取出的是字符串, 字典裝模型時(shí)候會(huì)報(bào)錯(cuò)

  • 下面再說(shuō)一下查表, 更行表 刪除表數(shù)據(jù)就不說(shuō)了,跟插入數(shù)據(jù)一樣 自己研究
  • 書(shū)寫(xiě)格式幾乎相同 就是返回結(jié)果是FMResultSet類(lèi)型(結(jié)果集), 這時(shí)候根據(jù)遍歷結(jié)果集取出每一條數(shù)據(jù)
    /**此種方式后面拼接的參數(shù)必須為對(duì)象 不可以為int double等基本數(shù)據(jù)類(lèi)型*/
    [dataBase executeQuery:@"select *From t_table;"];
    /**此種方式后面拼接的參數(shù)可以為int double等基本數(shù)據(jù)類(lèi)型 因?yàn)槭鞘褂玫恼嘉环?/
    [dataBase executeQueryWithFormat:@"SELECT name, age, score from t_table where name = %@", @"jake"];
    /**此種方式后面拼接的參數(shù)必須為對(duì)象 不可以為int double等基本數(shù)據(jù)類(lèi)型 將對(duì)象依次防近視數(shù)組*/
    [dataBase executeQuery:@"select *from t_table where age > ?" withArgumentsInArray:@[@12]];
  • 拿查整個(gè)表的全部數(shù)據(jù)為例
 FMResultSet * resultSet = [dataBase executeQuery:@"select *From t_table;"];
    while ([resultSet next]) {
        // 通過(guò)字段獲取 文本數(shù)據(jù)
        [resultSet stringForColumn:@"name"];
        // 也可以通過(guò)Column來(lái)獲取
        [resultSet stringForColumnIndex:2];
        
        // 通過(guò)字段獲取 對(duì)象數(shù)據(jù)
        [resultSet objectForColumnName:@"dict"];
        
    }
  • 關(guān)于FMResultSet使用結(jié)合如下
/* 獲取下一個(gè)記錄 */
       - (BOOL)next;
       /* 獲取記錄有多少列 */
       - (int)columnCount;
       /* 通過(guò)列名得到列序號(hào),通過(guò)列序號(hào)得到列名 */
       - (int)columnIndexForName:(NSString *)columnName;
       - (NSString *)columnNameForIndex:(int)columnIdx;
       /* 獲取存儲(chǔ)的整形值 */
       - (int)intForColumn:(NSString *)columnName;
       - (int)intForColumnIndex:(int)columnIdx;
       /* 獲取存儲(chǔ)的長(zhǎng)整形值 */
       - (long)longForColumn:(NSString *)columnName;
       - (long)longForColumnIndex:(int)columnIdx;
       /* 獲取存儲(chǔ)的布爾值 */
       - (BOOL)boolForColumn:(NSString *)columnName;
       - (BOOL)boolForColumnIndex:(int)columnIdx;
       /* 獲取存儲(chǔ)的浮點(diǎn)值 */
       - (double)doubleForColumn:(NSString *)columnName;
       - (double)doubleForColumnIndex:(int)columnIdx;
       /* 獲取存儲(chǔ)的字符串 */
       - (NSString *)stringForColumn:(NSString *)columnName;
       - (NSString *)stringForColumnIndex:(int)columnIdx;
       /* 獲取存儲(chǔ)的日期數(shù)據(jù) */
       - (NSDate *)dateForColumn:(NSString *)columnName;
       - (NSDate *)dateForColumnIndex:(int)columnIdx;
       /* 獲取存儲(chǔ)的二進(jìn)制數(shù)據(jù) */
       - (NSData *)dataForColumn:(NSString *)columnName;
       - (NSData *)dataForColumnIndex:(int)columnIdx;
       /* 獲取存儲(chǔ)的UTF8格式的C語(yǔ)言字符串 */
       - (const unsigned cahr *)UTF8StringForColumnName:(NSString *)columnName;
       - (const unsigned cahr *)UTF8StringForColumnIndex:(int)columnIdx;
       /* 獲取存儲(chǔ)的對(duì)象,只能是NSNumber、NSString、NSData、NSNull */
       - (id)objectForColumnName:(NSString *)columnName;
       - (id)objectForColumnIndex:(int)columnIdx;

FMDatabaseQueue

  • 如果項(xiàng)目中開(kāi)啟多個(gè)線程同時(shí)訪問(wèn)一個(gè)數(shù)據(jù)庫(kù)的時(shí)候,需要考慮到線程安全的問(wèn)題了,那么就要使用這個(gè)類(lèi)來(lái)對(duì)數(shù)據(jù)庫(kù)操作了, 那么我們還要理解一個(gè)概念 事物 常說(shuō)開(kāi)啟事物 提交事物 回滾事物 是什么意思呢? 為什么需要開(kāi)啟事物呢

  • 說(shuō)個(gè)情形就明白了,加入我們像一個(gè)數(shù)據(jù)庫(kù)表中插入一百條數(shù)據(jù), 我們可能會(huì)執(zhí)行一百條SQLite語(yǔ)句,如果當(dāng)我們執(zhí)行到一半的時(shí)候出錯(cuò)了,那么我們需要回滾, 讓之前執(zhí)行的的數(shù)據(jù)恢復(fù)之前數(shù)據(jù),也就是一句話,我們需要所有的語(yǔ)句都執(zhí)行成功才生效,那么我們就需要開(kāi)啟事物,當(dāng)確定所有的語(yǔ)句都執(zhí)行成功就提交事物, 如果中途出錯(cuò),那么就回滾事物

  • 首先我們不開(kāi)啟事物,就線程安全來(lái)使用FMDB

// 1.獲得數(shù)據(jù)庫(kù)路徑
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"daba.sqlist"];
    
    // 創(chuàng)建FMDatabaseQueue 同時(shí)會(huì)創(chuàng)建數(shù)據(jù)庫(kù) 如果數(shù)據(jù)庫(kù)不存在
    FMDatabaseQueue *baseQueue = [FMDatabaseQueue databaseQueueWithPath:path];
  • 當(dāng)我們對(duì)數(shù)據(jù)庫(kù)進(jìn)行CRUDde的時(shí)候調(diào)用- (void)inDatabase:(void (^)(FMDatabase *db))block, 在block回調(diào)給我的FMDatabase對(duì)象進(jìn)行操作 ,操作跟上面一樣的 例如
[baseQueue inDatabase:^(FMDatabase *db) {
        // 打開(kāi)數(shù)據(jù)庫(kù) 創(chuàng)建表
        BOOL isSuccess = [db open];
        if (!isSuccess) {
            NSLog(@"打開(kāi)數(shù)據(jù)庫(kù)失敗");
        }else{
            NSLog(@"打開(kāi)數(shù)據(jù)庫(kù)成功");
            
            // 插入數(shù)據(jù)
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        }
        
    }];
  • 使用一下開(kāi)啟事物, 加入我們插入同時(shí)插入十條數(shù)據(jù)
// 1.獲得數(shù)據(jù)庫(kù)路徑
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"daba.sqlist"];
    
    // 創(chuàng)建FMDatabaseQueue 同時(shí)會(huì)創(chuàng)建數(shù)據(jù)庫(kù) 如果數(shù)據(jù)庫(kù)不存在
    FMDatabaseQueue *baseQueue = [FMDatabaseQueue databaseQueueWithPath:path];
    
    [baseQueue inDatabase:^(FMDatabase *db) {
        // 打開(kāi)數(shù)據(jù)庫(kù) 創(chuàng)建表
        BOOL isSuccess = [db open];
        if (!isSuccess) {
            NSLog(@"打開(kāi)數(shù)據(jù)庫(kù)失敗");
        }else{
            NSLog(@"打開(kāi)數(shù)據(jù)庫(kù)成功");
            
            // 開(kāi)啟事物
            [db beginTransaction];
            
            // 插入數(shù)據(jù)
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            // 也可以在中途回滾 就是該次對(duì)數(shù)據(jù)庫(kù)的操作不生效 通常中途一般不回滾
            [db rollback];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            
            // 提交事物
            [db commit];
            
        }
        
    }];
  • 其實(shí)FMDB內(nèi)部已經(jīng)幫我們封裝好,只需要調(diào)用FMDatabaseQueue對(duì)象方法 - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block
[baseQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {

        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        // 如果中途想回滾 就這樣操作
        *rollback = YES;
        [db rollback];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
    }];
  • 下班了,不寫(xiě)了,大家如果發(fā)現(xiàn)有誤,謝謝反饋給我????
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容