swift下FMDB的使用
swift下FMDB的使用
在IOS中可以使用的存儲(chǔ)結(jié)構(gòu)有很多,可以使用文件進(jìn)行緩存,可以使用useDefault實(shí)現(xiàn)簡(jiǎn)單狀態(tài)的存儲(chǔ),此外IOS下有一個(gè)常用的數(shù)據(jù)庫(kù)框架–FMDB,它是對(duì)于SQLite的一層封裝,可以使用它完成基本的增刪查改,也可以對(duì)此完成事務(wù),回滾等復(fù)雜操作
對(duì)于FMDB的集成,我們可以直接使用cocoapod完成集成,就像如下的podfile
之后,就可以進(jìn)行操作了,但是由于我使用的是swift,FMDB是使用OC語(yǔ)言封裝的庫(kù),要使用的話(huà),就應(yīng)該在項(xiàng)目的根目錄下面創(chuàng)建一個(gè)bridge.h,在其中導(dǎo)入我們的FMDB
加完以后,我們還需要再info.plist中,進(jìn)行設(shè)置,使得我們的改動(dòng)內(nèi)容生效,點(diǎn)擊項(xiàng)目–TARGETS–Build Settings,其中有一個(gè)設(shè)置是swift compiler - General設(shè)置其中OC橋接文件為之前自定義的文件
之后的話(huà),就可以直接使用了,我們可以先定義一個(gè)公共的操作類(lèi),封裝數(shù)據(jù)的初始化和增刪查改等操作
先定義好我們的實(shí)體類(lèi)對(duì)象
首先來(lái)說(shuō),這個(gè)類(lèi)應(yīng)該是全局的單例對(duì)象,所以說(shuō),先設(shè)置一個(gè)static的對(duì)象,讓其他的類(lèi)調(diào)用來(lái)獲取到對(duì)象,之后,在使用的時(shí)候要先打開(kāi)db對(duì)象,這里需要注意的問(wèn)題就是,對(duì)于這個(gè)數(shù)據(jù)庫(kù),我們是通過(guò)一個(gè)文件路徑來(lái)生成的,如果原先就存在這個(gè)數(shù)據(jù)庫(kù),會(huì)直接打開(kāi)這個(gè)文件,如果不存在,就會(huì)先創(chuàng)建數(shù)據(jù)庫(kù),在進(jìn)行開(kāi)啟數(shù)據(jù)庫(kù)的操作,值得注意的是,在FMDB中,使用數(shù)據(jù)庫(kù)以后要及時(shí)關(guān)閉數(shù)據(jù)庫(kù),所以來(lái)說(shuō)open和close一般是成對(duì)出現(xiàn)的
import UIKitclass FMDBManager: NSObject {static let shared = FMDBManager();var dbUrl : String?;var FMDBEntity : FMDatabase?;var FMDBQueue : FMDatabaseQueue?;//打開(kāi)數(shù)據(jù)庫(kù),也就是創(chuàng)建數(shù)據(jù)庫(kù)func opendb(dbName : String, tableName : String) {//在doc文件夾下面創(chuàng)建新的文件夾,用來(lái)儲(chǔ)存數(shù)據(jù)庫(kù)let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true);let docPath = paths[0] + "/\(dbName)";self.dbUrl = docPath;//創(chuàng)建新的數(shù)據(jù)庫(kù)self.FMDBEntity = FMDatabase.init(path: self.dbUrl);//如果數(shù)據(jù)庫(kù)存在,就直接打開(kāi),如果不存在,則會(huì)現(xiàn)在磁盤(pán)上創(chuàng)建數(shù)據(jù)庫(kù),然后再打開(kāi)if self.FMDBEntity!.open() {print("數(shù)據(jù)庫(kù)打開(kāi)成功");//創(chuàng)建數(shù)據(jù)表self.initTable(t_name: tableName);}else {print("數(shù)據(jù)庫(kù)打開(kāi)失敗");}//數(shù)據(jù)庫(kù)每次操作完成以后就應(yīng)該釋放資源self.FMDBEntity!.close();}func initTable(t_name : String) {let sql = "CREATE TABLE IF NOT EXISTS \(t_name)( \n" +"id INTEGER PRIMARY KEY AUTOINCREMENT, \n" +"name TEXT, \n" +"age INTEGER \n" +"); \n"if self.FMDBEntity!.executeUpdate(sql, withArgumentsIn: []) {print("數(shù)據(jù)表創(chuàng)建成功");}else {print("數(shù)據(jù)表創(chuàng)建失敗");}}}這樣的話(huà),我們就完成了數(shù)據(jù)表的創(chuàng)建,如果要進(jìn)行增刪查改,我們就可以借助于FMDatabase執(zhí)行對(duì)應(yīng)的sql代碼,對(duì)于FMDB來(lái)說(shuō),它和一般的數(shù)據(jù)庫(kù)沒(méi)有區(qū)別,所以說(shuō),原先使用的sql基本上沒(méi)有變化,下面舉個(gè)例子,如果我們要增加一條記錄,那么需要執(zhí)行的sql是
insert into table_name (cloum1, cloum2, cloum3...) values(value1, value2, value3...)接下來(lái),我們就可以編寫(xiě)一個(gè)方法來(lái)執(zhí)行我們的sql,一般來(lái)說(shuō)有兩種方式
在這里,可以直接把參數(shù)嵌入到自定義的String中,拼接成完整的sql語(yǔ)句用來(lái)執(zhí)行,也可以使用?作為占位符,我使用的是占位符的方式,方法如下
而如果要進(jìn)行查詢(xún)操作時(shí),我們就會(huì)接觸到另外一個(gè)對(duì)象,那就是FMDB中的結(jié)果集FMResultSet,這個(gè)東西和jdbc中的結(jié)果集是相通的,可以進(jìn)行逐行的遍歷,得到每條數(shù)據(jù),然后就可以進(jìn)行相應(yīng)的解析,在組合成一個(gè)完整的對(duì)象,也就是下面的方法
func select(tableName : String, param : [String : AnyObject]) -> [PersonEntity] {let pId = param["id"];//定義增加的sqllet sql = "select * from \(tableName) where id = ?";//開(kāi)啟數(shù)據(jù)庫(kù)連接,執(zhí)行sql語(yǔ)句var persons : [PersonEntity] = [];if self.FMDBEntity!.open() {//數(shù)據(jù)庫(kù)連接已打開(kāi),傳入sql和參數(shù)if let queryResult = self.FMDBEntity?.executeQuery(sql, withArgumentsIn: [pId ?? 0]) {while queryResult.next() {let id = queryResult.int(forColumn: "id");let name = queryResult.string(forColumn: "name") ?? "";let age = queryResult.int(forColumn: "age");let p = PersonEntity();p.initParam(id: Int(id), name: String(name), age: Int(age));persons.append(p);}}}self.FMDBEntity!.close();return persons;}下面還有刪除和修改的代碼,沒(méi)有什么特別之處了,就不再贅述了
func update(tableName : String, param : [String : AnyObject]) {//定義修改的sqllet sql = "update \(tableName) set name = ? where id = ?";//開(kāi)啟數(shù)據(jù)庫(kù)連接,執(zhí)行sql語(yǔ)句if self.FMDBEntity!.open() {//數(shù)據(jù)庫(kù)連接已打開(kāi),傳入sql和參數(shù)if self.FMDBEntity!.executeUpdate(sql, withArgumentsIn: ["張老道", 1]) {print("操作完成");}else{print("操作失敗");}}self.FMDBEntity!.close();}func delete(tableName : String, param : [String : AnyObject]) {//定義刪除的sqllet sql = "delete from \(tableName) where id = ?";//開(kāi)啟數(shù)據(jù)庫(kù)連接,執(zhí)行sql語(yǔ)句if self.FMDBEntity!.open() {//數(shù)據(jù)庫(kù)連接已打開(kāi),傳入sql和參數(shù)if self.FMDBEntity!.executeUpdate(sql, withArgumentsIn: [1]) {print("操作完成");}else{print("操作失敗");}}self.FMDBEntity!.close();}有點(diǎn)意思的這個(gè)數(shù)據(jù)庫(kù)里面的事務(wù)操作,在FMDB中事務(wù)操作依賴(lài)于一個(gè)隊(duì)列來(lái)實(shí)現(xiàn),那就是FMDatabaseQueue,先貼出來(lái)代碼,然后再分析一下,先是隊(duì)列的初始化
//執(zhí)行之前需要先初始化數(shù)據(jù)庫(kù)func openQueue(dbName : String, tableName : String) {let path = self.dbUrl ?? "";if path == "" {print("要先完成初始化");self.opendb(dbName: dbName, tableName: tableName);}self.FMDBQueue = FMDatabaseQueue.init(path: self.dbUrl);}之后執(zhí)行批量執(zhí)行的代碼
@objc func batchHandle() {print("批量插入");FMDBManager.shared.FMDBQueue?.inTransaction({ (db, rollback) inlet trueTable = "t_Student";let errorTable = "t_Sent";for i in 40..<50{var sql = "insert into \(trueTable) (name, age) values(?, ?)";if i == 45 {sql = "insert into \(errorTable) (name, age) values(?, ?)";}let result : Bool = db.executeUpdate(sql, withArgumentsIn: ["張啟山", i]);if result {print("插入數(shù)據(jù):\(i)");}else{print("出現(xiàn)錯(cuò)誤,開(kāi)始回滾");rollback.pointee = true;return ;}}})}所以來(lái)說(shuō),進(jìn)行批量查詢(xún)的代碼關(guān)鍵就在inTransaction這個(gè)方法中,如果直接點(diǎn)進(jìn)去,我們會(huì)到達(dá)源代碼中的這個(gè)位置
直接往里跳,會(huì)到具體的代碼實(shí)現(xiàn)
不難看出,接下來(lái),我們會(huì)跳轉(zhuǎn)到beginTransaction方法,那這個(gè)方法執(zhí)行內(nèi)容又是什么呢,其實(shí)就只有一行代碼
- (BOOL)beginTransaction {BOOL b = [self executeUpdate:@"begin exclusive transaction"];if (b) {_isInTransaction = YES;}return b; }就是執(zhí)行了begin exclusive transaction,然后由于我們實(shí)現(xiàn)了源代碼里面的block,會(huì)在這條執(zhí)行以后粘貼上十條sql,然后根據(jù)shouldRollback的值決定最后的代碼,我們?cè)谧约旱拇a執(zhí)行時(shí),通過(guò)判斷每一插入語(yǔ)句的執(zhí)行結(jié)果,決定返回的布爾值,然后如果每條代碼都能執(zhí)行,就提交commit,所有代碼提交生效,否則就提交rollback,所有代碼回滾,完成了事務(wù)的功能
參考文章
第一篇文章
第二篇文章
第三篇文章
對(duì)于更多的FMDB和Model封裝操作,可以參考下面這篇文章,所的也很豐富,有興趣的可以自己研究一下
實(shí)體類(lèi)與數(shù)據(jù)庫(kù)表的關(guān)聯(lián)映射
總結(jié)
以上是生活随笔為你收集整理的swift下FMDB的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 网络渗透就业学习路线
- 下一篇: Prim最小生成树算法