[iOS]數(shù)據(jù)庫(kù)第三方框架FMDB詳細(xì)講解

[iOS]數(shù)據(jù)庫(kù)第三方框架FMDB詳細(xì)講解


初識(shí)FMDB


iOS中原生的SQLite API在進(jìn)行數(shù)據(jù)存儲(chǔ)的時(shí)候,需要使用C語(yǔ)言中的函數(shù),操作比較麻煩。于是,就出現(xiàn)了一系列將SQLite API進(jìn)行封裝的庫(kù),例如FMDB、PlausibleDatabase、sqlitepersistentobjects等。

FMDB是一款簡(jiǎn)潔、易用的封裝庫(kù)。因此,在這里推薦使用第三方框架FMDB,它是對(duì)libsqlite3框架的封裝,用起來(lái)的步驟與SQLite使用類(lèi)似,并且它對(duì)于多線(xiàn)程的并發(fā)操作進(jìn)行了處理,所以是線(xiàn)程安全的。


FMDB PK Sqlite


  • 優(yōu)點(diǎn):
    • 對(duì)多線(xiàn)程的并發(fā)操作進(jìn)行處理,所以是線(xiàn)程安全的;
    • 以O(shè)C的方式封裝了SQLite的C語(yǔ)言API,使用起來(lái)更加的方便;
    • FMDB是輕量級(jí)的框架,使用靈活。
  • 缺點(diǎn):
    • 因?yàn)樗荗C的語(yǔ)言封裝的,只能在ios開(kāi)發(fā)的時(shí)候使用,所以在實(shí)現(xiàn)跨平臺(tái)操作的時(shí)候存在局限性。

FMDB框架中重要的框架類(lèi)


  • FMDatabase
    • FMDatabase對(duì)象就代表一個(gè)單獨(dú)的SQLite數(shù)據(jù)庫(kù),用來(lái)執(zhí)行SQL語(yǔ)句
  • FMResultSet
    • 使用FMDatabase執(zhí)行查詢(xún)后的結(jié)果集
  • FMDatabaseQueue
    • 用于在多線(xiàn)程中執(zhí)行多個(gè)查詢(xún)或更新,它是線(xiàn)程安全的

FMDB使用步驟


  • 下載FMDB文件GitHub,并將FMDB文件夾添加到項(xiàng)目中(也可使用CocoaPods導(dǎo)入)
  • 導(dǎo)入libsqlite3.0框架,導(dǎo)入頭文件FMDatabase.h
  • 代碼實(shí)現(xiàn),與SQLite使用步驟相似,創(chuàng)建數(shù)據(jù)庫(kù)路徑,獲得數(shù)據(jù)庫(kù)路徑,打開(kāi)數(shù)據(jù)庫(kù),然后對(duì)數(shù)據(jù)庫(kù)進(jìn)行增、刪、改、查操作,最后關(guān)閉數(shù)據(jù)庫(kù)。
step.png
數(shù)據(jù)庫(kù)創(chuàng)建

創(chuàng)建FMDatabase對(duì)象時(shí)參數(shù)為SQLite數(shù)據(jù)庫(kù)文件路徑,該路徑可以是以下三種方式之一

  • 文件路徑。該文件路徑無(wú)需真實(shí)存在,如果不存在會(huì)自動(dòng)創(chuàng)建

  • 空字符串(@“”)。表示會(huì)在臨時(shí)目錄創(chuàng)建一個(gè)空的數(shù)據(jù)庫(kù),當(dāng)FMDatabase連接關(guān)閉時(shí),文件也會(huì)被刪除

  • NULL。將創(chuàng)建一個(gè)內(nèi)在數(shù)據(jù)庫(kù),同樣的,當(dāng)FMDatabase連接關(guān)閉時(shí),數(shù)據(jù)將會(huì)被銷(xiāo)毀

  • 本文中使用的測(cè)試模型類(lèi).h

student.png
數(shù)據(jù)庫(kù)使用FMDB框架代碼操作
  • 使用FMDataBase類(lèi)建立數(shù)據(jù)庫(kù)

    //1.獲得數(shù)據(jù)庫(kù)文件的路徑
    NSString *doc =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)  lastObject];                  
    
    NSString *fileName = [doc stringByAppendingPathComponent:@“student.sqlite”];
        
    //2.獲得數(shù)據(jù)庫(kù)
    FMDatabase *db = [FMDatabase databaseWithPath:fileName];
    
    //3.使用如下語(yǔ)句,如果打開(kāi)失敗,可能是權(quán)限不足或者資源不足。通常打開(kāi)完操作操作后,需要調(diào)用 close 方法來(lái)關(guān)閉數(shù)據(jù)庫(kù)。在和數(shù)據(jù)庫(kù)交互 之前,數(shù)據(jù)庫(kù)必須是打開(kāi)的。如果資源或權(quán)限不足無(wú)法打開(kāi)或創(chuàng)建數(shù)據(jù)庫(kù),都會(huì)導(dǎo)致打開(kāi)失敗。
    if ([db open])
    {
        //4.創(chuàng)表
        BOOL result = [db executeUpdate:@“CREATE TABLE IF NOT EXISTS t_student (id integer PRIMARY KEY AUTOINCREMENT, name text NOT NULL, age integer NOT NULL);”];
        if (result)
        {
            NSLog(@“創(chuàng)建表成功”);
        }
    }
    
  • 查看sql表

  • 根據(jù)路徑fileName在Finder中搜索.sqlite文件,并復(fù)制到桌面

  • 使用火狐瀏覽器工具下的SQLite Manager打開(kāi).sqlite文件


    2.png
  • 數(shù)據(jù)表結(jié)構(gòu)

sql.png

使用FMDataBase類(lèi)執(zhí)行數(shù)據(jù)庫(kù)命令SQL

一切不是SELECT命令的命令都視為更新。這包括 CREAT,UPDATE,INSERT,ALTER,BEGIN,COMMIT,DETACH,DELETE,DROP,END,EXPLAIN,VACUUM,REPLACE等。

簡(jiǎn)單來(lái)說(shuō),只要不是以SELECT開(kāi)頭的命令都是更新命令。

執(zhí)行更新返回一個(gè)BOOL值。YES表示 執(zhí)行成功,否則表示有錯(cuò)誤。你可以調(diào)用 -lastErrorMessage 和 -lastErrorCode方法來(lái)得到更多信息。


  • 使用FMDataBase類(lèi)執(zhí)行數(shù)據(jù)庫(kù)插入命令SQLinsert into

    int age = 42;
    
    //1.executeUpdate:不確定的參數(shù)用?來(lái)占位(后面參數(shù)必須是oc對(duì)象,;代表語(yǔ)句結(jié)束)
    [self.db executeUpdate:@“INSERT INTO t_student (name, age) VALUES (?,?);”,name,@(age)];
    
    //2.executeUpdateWithForamat:不確定的參數(shù)用%@,%d等來(lái)占位 (參數(shù)為原始數(shù)據(jù)類(lèi)型,執(zhí)行語(yǔ)句不區(qū)分大小寫(xiě))
    [self.db executeUpdateWithForamat:@“insert into t_student (name,age) values (%@,%i);”,name,age];
         
    //3.參數(shù)是數(shù)組的使用方式
    [self.db executeUpdate:@“INSERT INTO     
    t_student(name,age) VALUES  (?,?);”withArgumentsInArray:@[name,@(age                 )]];
    
  • 使用FMDataBase類(lèi)執(zhí)行數(shù)據(jù)庫(kù)刪除命令SQLdelete

    //1.不確定的參數(shù)用?來(lái)占位 (后面參數(shù)必須是oc對(duì)象,需要將int包裝成OC對(duì)象)
    int idNum = 101;
    [self.db executeUpdate:@“delete from t_student where id = ?;”,@(idNum)];
    
    //2.不確定的參數(shù)用%@,%d等來(lái)占位
    [self.db executeUpdateWithFormat:@“delete from t_student where name = %@;”,@“apple_name”];
    
  • 使用FMDataBase類(lèi)執(zhí)行數(shù)據(jù)庫(kù)修改命令SQLupdate

    //修改學(xué)生的名字
    [self.db executeUpdate:@“update t_student set name = ? where name = ?”,newName,oldName];
    
  • 使用FMDataBase類(lèi)執(zhí)行數(shù)據(jù)庫(kù)查詢(xún)命令SQLselect ... from

    • SELECT命令就是查詢(xún),執(zhí)行查詢(xún)的方法是以-excuteQuery開(kāi)頭的。
    • 執(zhí)行查詢(xún)時(shí),如果成功返回FMResultSet對(duì)象,錯(cuò)誤返回nil。與執(zhí)行更新相當(dāng),支持使用NSError參數(shù)。
    • 同時(shí),你也可以使用-lastErrorCode和-lastErrorMessage獲知錯(cuò)誤信息。
  • FMResultSet獲取不同數(shù)據(jù)格式的方法

  • intForColumn:

  • longForColumn:

  • longLongIntForColumn:

  • boolForColumn:

  • doubleForColumn:

  • stringForColumn:

  • dataForColumn:

  • dataNoCopyForColumn:

  • UTF8StringForColumnIndex:

  • objectForColumn:

  • 使用FMResultSet獲取查詢(xún)語(yǔ)句結(jié)果

     //查詢(xún)整個(gè)表
    FMResultSet *resultSet = [self.db executeQuery:@“select * from t_student;”];
     
     //根據(jù)條件查詢(xún)
    FMResultSet *resultSet = [self.db executeQuery:@“select * from t_student where id<?;”@(14)];
    
     //遍歷結(jié)果集合   
      
    while ([resultSet  next])
     
      {
        int idNum = [resultSet intForColumn:@“id”];
    
        NSString *name = [resultSet    
        objectForColumn:@“name”];
       
        int age = [resultSet intForColumn:@“age”];
      }
          
    
  • 使用FMDataBase類(lèi)執(zhí)行數(shù)據(jù)庫(kù)銷(xiāo)毀命令SQLdrop ...

    //如果表格存在 則銷(xiāo)毀
    [self.db executeUpadate:@“drop table if exists t_student;”];
    
  • 使用FMDatabaseQueue類(lèi)實(shí)現(xiàn)多線(xiàn)程操作

在多個(gè)線(xiàn)程中同時(shí)使用一個(gè)FMDatabase實(shí)例是不明智的?,F(xiàn)在你可以為每 個(gè)線(xiàn)程創(chuàng)建一個(gè)FMDatabase對(duì)象,不要讓多個(gè)線(xiàn)程分享同一個(gè)實(shí)例,他無(wú) 法在多個(gè)線(xiàn)程中同事使用。否則程序會(huì)時(shí)不時(shí)崩潰或者報(bào)告異常。所以,不要 初始化FMDatabase對(duì)象,然后在多個(gè)線(xiàn)程中使用。這時(shí)候,我們就需要使 用FMDatabaseQueue來(lái)創(chuàng)建隊(duì)列執(zhí)行事務(wù)。

 //1.創(chuàng)建隊(duì)列
 FMDatabaseQueue *queue = [FMDatabaseQueue   
 databaseQueueWithPath:aPath];
  __block BOOL whoopsSomethingWrongHappened = true;
  
 //2.把任務(wù)包裝到事務(wù)里
 [queue inTransaction:^(FMDatabase *db, BOOL *rollback) 
  {  
 whoopsSomethingWrongHappened &=  [db     executeUpdate:@“INSERT INTO myTable VALUES (?)”,    [NSNumber numberWith:1]];
whoopsSomethingWrongHappened &= [db
executeUpdata:@“INSERT INTO myTable VALUES (?)”, 
[NSNumber numberWithInt:2]];

whoopsSomethingWrongHappened &= [db  
executeUpdata:@“INSERT INTO myTable VALUES (?)”[NSNumber  
numberWithInt:3]];
//如果有錯(cuò)誤 返回
if (!whoopsSomethingWrongHappened)
  { 
    *rollback = YES;
      return;
  }
}];

好了,到此為止,相信你已經(jīng)能夠使用FMDB進(jìn)行數(shù)據(jù)持久化了,它的好與壞 只有在不斷地使用過(guò)程中才能發(fā)現(xiàn)了解。所以,希望大家學(xué)會(huì)了以后還是要多  寫(xiě)多練多使用。另外,誠(chéng)心希望大家多提寶貴意見(jià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)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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