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

初識FMDB

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

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

FMDB PK Sqlite

優(yōu)點(diǎn):

對多線程的并發(fā)操作進(jìn)行處理,所以是線程安全的;

以O(shè)C的方式封裝了SQLite的C語言API,使用起來更加的方便;

FMDB是輕量級的框架,使用靈活。

缺點(diǎn):

因為它是OC的語言封裝的,只能在ios開發(fā)的時候使用,所以在實現(xiàn)跨平臺操作的時候存在局限性。

FMDB框架中重要的框架類

FMDatabase

FMDatabase對象就代表一個單獨(dú)的SQLite數(shù)據(jù)庫,用來執(zhí)行SQL語句

FMResultSet

使用FMDatabase執(zhí)行查詢后的結(jié)果集

FMDatabaseQueue

用于在多線程中執(zhí)行多個查詢或更新,它是線程安全的

FMDB使用步驟

下載FMDB文件GitHub,并將FMDB文件夾添加到項目中(也可使用CocoaPods導(dǎo)入)

導(dǎo)入libsqlite3.0框架,導(dǎo)入頭文件FMDatabase.h

代碼實現(xiàn),與SQLite使用步驟相似,創(chuàng)建數(shù)據(jù)庫路徑,獲得數(shù)據(jù)庫路徑,打開數(shù)據(jù)庫,然后對數(shù)據(jù)庫進(jìn)行增、刪、改、查操作,最后關(guān)閉數(shù)據(jù)庫。

step.png

數(shù)據(jù)庫創(chuàng)建

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

文件路徑。該文件路徑無需真實存在,如果不存在會自動創(chuàng)建

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

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

本文中使用的測試模型類.h

student.png

數(shù)據(jù)庫使用FMDB框架代碼操作

使用FMDataBase類建立數(shù)據(jù)庫

//1.獲得數(shù)據(jù)庫文件的路徑

NSString*doc =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)? lastObject];

NSString*fileName = [doc stringByAppendingPathComponent:@“student.sqlite”];

//2.獲得數(shù)據(jù)庫

FMDatabase *db = [FMDatabase databaseWithPath:fileName];

//3.使用如下語句,如果打開失敗,可能是權(quán)限不足或者資源不足。通常打開完操作操作后,需要調(diào)用 close 方法來關(guān)閉數(shù)據(jù)庫。在和數(shù)據(jù)庫交互 之前,數(shù)據(jù)庫必須是打開的。如果資源或權(quán)限不足無法打開或創(chuàng)建數(shù)據(jù)庫,都會導(dǎo)致打開失敗。

if([db open])

{

//4.創(chuàng)表

BOOLresult = [db executeUpdate:@“CREATE TABLE IF NOT EXISTS t_student (idinteger PRIMARY KEY AUTOINCREM ENT, name text NOTNULL, age integer NOTNULL);”];

if(result)

{

NSLog(@“創(chuàng)建表成功”);

}

}

查看sql表

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

使用火狐瀏覽器工具下的SQLite Manager打開.sqlite文件

2.png

數(shù)據(jù)表結(jié)構(gòu)

sql.png

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

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

簡單來說,只要不是以SELECT開頭的命令都是更新命令。

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

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

int age = 42;

//1.executeUpdate:不確定的參數(shù)用?來占位(后面參數(shù)必須是oc對象,;代表語句結(jié)束)

[self.db executeUpdate:@“INSERTINTOt_student (name, age)VALUES(?,?);”,name,@(age)];

//2.executeUpdateWithForamat:不確定的參數(shù)用%@,%d等來占位 (參數(shù)為原始數(shù)據(jù)類型,執(zhí)行語句不區(qū)分大小寫)

[self.db executeUpdateWithForamat:@“insertintot_student (name,age)values(%@,%i);”,name,age];

//3.參數(shù)是數(shù)組的使用方式

[self.db executeUpdate:@“INSERTINTO

t_student(name,age)VALUES(?,?);”withArgumentsInArray:@[name,@(age????????????? )]];

使用FMDataBase類執(zhí)行數(shù)據(jù)庫刪除命令SQLdelete

//1.不確定的參數(shù)用?來占位 (后面參數(shù)必須是oc對象,需要將int包裝成OC對象)

intidNum =101;

[self.db executeUpdate:@“deletefrom t_student where id = ?;”,@(idNum)];

//2.不確定的參數(shù)用%@,%d等來占位

[self.db executeUpdateWithFormat:@“deletefrom t_student where name = %@;”,@“apple_name”];

使用FMDataBase類執(zhí)行數(shù)據(jù)庫修改命令SQLupdate

//修改學(xué)生的名字

[self.db executeUpdate:@“updatet_studentsetname= ?wherename= ?”,newName,oldName];

使用FMDataBase類執(zhí)行數(shù)據(jù)庫查詢命令SQLselect ... from

SELECT命令就是查詢,執(zhí)行查詢的方法是以-excuteQuery開頭的。

執(zhí)行查詢時,如果成功返回FMResultSet對象,錯誤返回nil。與執(zhí)行更新相當(dāng),支持使用NSError參數(shù)。

同時,你也可以使用-lastErrorCode和-lastErrorMessage獲知錯誤信息。

FMResultSet獲取不同數(shù)據(jù)格式的方法

intForColumn:

longForColumn:

longLongIntForColumn:

boolForColumn:

doubleForColumn:

stringForColumn:

dataForColumn:

dataNoCopyForColumn:

UTF8StringForColumnIndex:

objectForColumn:

使用FMResultSet獲取查詢語句結(jié)果

//查詢整個表

FMResultSet *resultSet = [self.db execute Query:@“select* from t_student;”];

//根據(jù)條件查詢

FMResultSet *resultSet = [self.db executeQuery:@“select* from t_student where id

//遍歷結(jié)果集合

while([resultSet? next])

{

intidNum = [resultSet intForColumn:@“id”];

NSString *name = [resultSet

objectForColumn:@“name”];

intage = [resultSet intForColumn:@“age”];

}

使用FMDataBase類執(zhí)行數(shù)據(jù)庫銷毀命令SQLdrop ...

//如果表格存在 則銷毀

[self.db executeUpadate:@“droptableifexistst_student;”];

使用FMDatabaseQueue類實現(xiàn)多線程操作

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

//1.創(chuàng)建隊列

FMDatabaseQueue *queue = [FMDatabaseQueue

databaseQueueWithPath:aPath];

__block BOOL whoopsSomethingWrongHappened =true;

//2.把任務(wù)包裝到事務(wù)里

[queueinTransaction:^(FMDatabase *db, BOOL *rollback)

{

whoopsSomethingWrongHappened &=? [dbexecuteUpdate:@“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]];

//如果有錯誤 返回

if(!whoopsSomethingWrongHappened)

{

*rollback = YES;

return;

}

}];

自己測試:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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