[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ù)。

數(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

數(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)

使用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 intoint 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),或者溝通一些好的想法。^^
