iOS SQLite、CoreData、FMDB數(shù)據(jù)庫詳解

本文參考iOS SQLite、CoreData、FMDB數(shù)據(jù)庫詳解,非常感謝該作者

序言

在iOS開發(fā)中數(shù)據(jù)存儲的方式可以歸納為兩類:一類是存儲為文件,另一類是存儲到數(shù)據(jù)庫。例如前面IOS開發(fā)系列—Objective-C之Foundation框架的文章中提到歸檔、plist文件存儲,包括偏好設置其本質(zhì)都是存儲為文件,只是說歸檔或者plist文件存儲可以選擇保存到沙盒中,而偏好設置系統(tǒng)已經(jīng)規(guī)定只能保存到沙盒的Library/Preferences目錄。當然,文件存儲并不作為本文的重點內(nèi)容。本文重點還是說數(shù)據(jù)庫存儲,做過數(shù)據(jù)庫開發(fā)的朋友應該知道,可以通過SQL直接訪問數(shù)據(jù)庫,也可以通過ORM進行對象關系映射訪問數(shù)據(jù)庫。這兩種方式恰恰對應iOS中SQLite和Core Data的內(nèi)容,在此將重點進行分析:

一 SQLite

SQLite是目前主流的嵌入式關系型數(shù)據(jù)庫,其最主要的特點就是輕量級、跨平臺,當前很多嵌入式操作系統(tǒng)都將其作為數(shù)據(jù)庫首選。雖然SQLite是一款輕型數(shù)據(jù)庫,但是其功能也絕不亞于很多大型關系數(shù)據(jù)庫。學習數(shù)據(jù)庫就要學習其相關的定義、操作、查詢語言,也就是大家日常說得SQL語句。和其他數(shù)據(jù)庫相比,SQLite中的SQL語法并沒有太大的差別,因此這里對于SQL語句的內(nèi)容不會過多贅述,大家可以參考SQLite中其他SQL相關的內(nèi)容,這里還是重點講解iOS中如何使用SQLite構(gòu)建應用程序。先看一下SQLite數(shù)據(jù)庫的幾個特點:

  • 基于C語言開發(fā)的輕型數(shù)據(jù)庫
  • 在iOS中需要使用C語言語法進行數(shù)據(jù)庫操作、訪問(無法使用ObjC直接訪問,因為libqlite3框架基于C語言編寫)
  • SQLite中采用的是動態(tài)數(shù)據(jù)類型,即使創(chuàng)建時定義了一種類型,在實際操作時也可以存儲其他類型,但是推薦建庫時使用合適的類型(特別是應用需要考慮跨平臺的情況時)
  • 建立連接后通常不需要關閉連接(盡管可以手動關閉)
在iOS中操作SQLite數(shù)據(jù)庫可以分為以下幾步(注意先在項目中導入libsqlite3框架):

1.打開數(shù)據(jù)庫,利用sqlite3_open()打開數(shù)據(jù)庫會指定一個數(shù)據(jù)庫文件保存路徑,如果文件存在則直接打開,否則創(chuàng)建并打開。打開數(shù)據(jù)庫會得到一個sqlite3類型的對象,后面需要借助這個對象進行其他操作。

2.執(zhí)行SQL語句,執(zhí)行SQL語句又包括有返回值的語句和無返回值語句。

3.對于無返回值的語句(如增加、刪除、修改等)直接通過sqlite3_exec()函數(shù)執(zhí)行;

4.對于有返回值的語句則首先通過sqlite3_prepare_v2()進行sql語句評估(語法檢測),然后通過sqlite3_step()依次取出查詢結(jié)果的每一行數(shù)據(jù),對于每行數(shù)據(jù)都可以通過對應的sqlite3_column_類型()方法獲得對應列的數(shù)據(jù),如此反復循環(huán)直到遍歷完成。當然,最后需要釋放句柄。

在整個操作過程中無需管理數(shù)據(jù)庫連接,對于嵌入式SQLite操作是持久連接(盡管可以通過sqlite3_close()關閉),不需要開發(fā)人員自己釋放連接。縱觀整個操作過程,其實與其他平臺的開發(fā)沒有明顯的區(qū)別,較為麻煩的就是數(shù)據(jù)讀取,在iOS平臺中使用C進行數(shù)據(jù)讀取采用了游標的形式,每次只能讀取一行數(shù)據(jù),較為麻煩。因此實際開發(fā)中不妨對這些操作進行封裝:

二 Core Data

當前,各類應用開發(fā)中只要牽扯到數(shù)據(jù)庫操作通常都會用到一個概念“對象關系映射(ORM)”。例如在Java平臺使用Hibernate,在.NET平臺使用Entity Framework、Linq、NHibernate等。在iOS中也不例外,iOS中ORM框架首選Core Data,這是官方推薦的,不需要借助第三方框架。無論是哪種平臺、哪種技術,ORM框架的作用都是相同的,那就是將關系數(shù)據(jù)庫中的表(準確的說是實體)轉(zhuǎn)換為程序中的對象,其本質(zhì)還是對數(shù)據(jù)庫的操作(例如Core Data中如果存儲類型配置為SQLite則本質(zhì)還是操作的SQLite數(shù)據(jù)庫)。細心的朋友應該已經(jīng)注意到,在上面的SQLite中其實我們在KCMainViewController中進行的數(shù)據(jù)庫操作已經(jīng)轉(zhuǎn)換為了對象操作,服務層中的方法中已經(jīng)將對數(shù)據(jù)庫的操作封裝起來,轉(zhuǎn)換為了對Model的操作,這種方式已經(jīng)是面向?qū)ο蟮?。上述通過將對象映射到實體的過程完全是手動完成的,相對來說操作比較復雜,就拿對KCStatus對象的操作來說:首先要手動創(chuàng)建數(shù)據(jù)庫(Status表),其次手動創(chuàng)建模型KCStatus,接著創(chuàng)建服務層KCStatusService。Core Data正是為了解決這個問題而產(chǎn)生的,它將數(shù)據(jù)庫的創(chuàng)建、表的創(chuàng)建、對象和表的轉(zhuǎn)換等操作封裝起來,簡化了我們的操作(注意Core Data只是將對象關系的映射簡化了,并不是把服務層替代了,這一點大家需要明白)。

使用Core Data進行數(shù)據(jù)庫存取并不需要手動創(chuàng)建數(shù)據(jù)庫,這個過程完全由Core Data框架完成,開發(fā)人員面對的是模型,主要的工作就是把模型創(chuàng)建起來,具體數(shù)據(jù)庫如何創(chuàng)建則不用管。在iOS項目中添加“Data Model”文件。然后在其中創(chuàng)建實體和關系:

模型創(chuàng)建的過程中需要注意:

  • 實體對象不需要創(chuàng)建ID主鍵,Attributes中應該是有意義屬性(創(chuàng)建過程中應該考慮對象的屬性而不是數(shù)據(jù)庫中表有幾個字段,盡管多數(shù)屬性會對應表的字段)。

  • 所有的屬性應該指定具體類型(盡管在SQLite中可以不指定),因為實體對象會對應生成ObjC模型類。

  • 實體對象中其他實體對象類型的屬性應該通過Relationships建立,并且注意實體之間的對應關系(例如一個用戶有多條微博,而一條微博則只屬于一個用戶,用戶和微博形成一對多的關系)。

有幾點需要注意:
1.所有的實體類型都繼承于NSManagedObject,每個NSManagedObject對象對應著數(shù)據(jù)庫中一條記錄。
2.集合屬性(例如User中的status)生成了訪問此屬性的分類方法。
3.使用@dynamic代表具體屬性實現(xiàn),具體實現(xiàn)細節(jié)不需要開發(fā)人員關心。

當然,了解了這些還不足以完成數(shù)據(jù)的操作。究竟Core Data具體的設計如何,要完成數(shù)據(jù)的存取我們還需要了解一下Core Data幾個核心的類。

1.Persistent Object Store:可以理解為存儲持久對象的數(shù)據(jù)庫(例如SQLite,注意Core Data也支持其他類型的數(shù)據(jù)存儲,例如xml、二進制數(shù)據(jù)等)。

2.Managed Object Model:對象模型,對應Xcode中創(chuàng)建的模型文件。

3.Persistent Store Coordinator:對象模型和實體類之間的轉(zhuǎn)換協(xié)調(diào)器,用于管理不同存儲對象的上下文。

4.Managed Object Context:對象管理上下文,負責實體對象和數(shù)據(jù)庫之間的交互。

Core Data使用

Core Data使用起來相對直接使用SQLite3的API而言更加的面向?qū)ο?,操作過程通常分為以下幾個步驟:

1.創(chuàng)建管理上下文

創(chuàng)建管理上下可以細分為:加載模型文件->指定數(shù)據(jù)存儲路徑->創(chuàng)建對應數(shù)據(jù)類型的存儲->創(chuàng)建管理對象上下方并指定存儲。

經(jīng)過這幾個步驟之后可以得到管理對象上下文NSManagedObjectContext,以后所有的數(shù)據(jù)操作都由此對象負責。同時如果是第一次創(chuàng)建上下文,Core Data會自動創(chuàng)建存儲文件(例如這里使用SQLite3存儲),并且根據(jù)模型對象創(chuàng)建對應的表結(jié)構(gòu)。

2.查詢數(shù)據(jù)

對于有條件的查詢,在Core Data中是通過謂詞來實現(xiàn)的。首先創(chuàng)建一個請求,然后設置請求條件,最后調(diào)用上下文執(zhí)行請求的方法。

3.插入數(shù)據(jù)

插入數(shù)據(jù)需要調(diào)用實體描述對象NSEntityDescription返回一個實體對象,然后設置對象屬性,最后保存當前上下文即可。這里需要注意,增、刪、改操作完最后必須調(diào)用管理對象上下文的保存方法,否則操作不會執(zhí)行。

4.刪除數(shù)據(jù)

刪除數(shù)據(jù)可以直接調(diào)用管理對象上下文的deleteObject方法,刪除完保存上下文即可。注意,刪除數(shù)據(jù)前必須先查詢到對應對象。

5.修改數(shù)據(jù)

修改數(shù)據(jù)首先也是取出對應的實體對象,然后通過修改對象的屬性,最后保存上下文。

調(diào)試

雖然Core Data(如果使用SQLite數(shù)據(jù)庫)操作最終轉(zhuǎn)換為SQL操作,但是調(diào)試起來卻不想操作SQL那么方便。特別是對于初學者而言經(jīng)常出現(xiàn)查詢報錯的問題,如果能看到最終生成的SQL語句自然對于調(diào)試很有幫助。事實上在Xcode中是支持Core Data調(diào)試的,具體操作:Product-Scheme-Edit Scheme-Run-Arguments中依次添加兩個參數(shù)(注意參數(shù)順序不能錯):-com.apple.CoreData.SQLDebug、

注意:如果模型發(fā)生了變化,此時可以重新生成實體類文件,但是所生成的數(shù)據(jù)庫并不會自動更新,這時需要考慮重新生成數(shù)據(jù)庫并遷移原有的數(shù)據(jù)。

三 FMDB

相比于SQLite3來說Core Data存在著諸多優(yōu)勢,它面向?qū)ο?,開發(fā)人員不必過多的關心更多數(shù)據(jù)庫操作知識,同時它基于ObjC操作,書寫更加優(yōu)雅等。但是它本身也存在著一定的限制,例如如果考慮到跨平臺,則只能選擇SQLite,因為無論是iOS還是Android都可以使用同一個數(shù)據(jù)庫,降低了開發(fā)成本和維護成本。其次是當前多數(shù)ORM框架都存在的性能問題,因為ORM最終轉(zhuǎn)化為SQL操作,其中牽扯到模型數(shù)據(jù)轉(zhuǎn)化,其性能自然比不上直接使用SQL操作數(shù)據(jù)庫。那么有沒有更好的選擇呢?答案就是對SQLite進行封裝。

其實通過前面對于SQLite的分析,大家應該已經(jīng)看到KCDbManager就是對于SQLite封裝的結(jié)果,開發(fā)人員面對的只有SQL和ObjC方法,不用過多l(xiāng)ibsqlite3的C語言API。但它畢竟只是一個簡單的封裝,還有更多的細節(jié)沒有考慮,例如如何處理并發(fā)安全性,如何更好的處理事務等。因此,這里推薦使用第三方框架FMDB,整個框架非常輕量級但又不失靈活性,也是很多企業(yè)開發(fā)的首選。

步驟

1.FMDB既然是對于libsqlite3框架的封裝,自然使用起來也是類似的,使用前也要打開一個數(shù)據(jù)庫,這個數(shù)據(jù)庫文件存在則直接打開否則會創(chuàng)建并打開。這里FMDB引入了一個MFDatabase對象來表示數(shù)據(jù)庫,打開數(shù)據(jù)庫和后面的數(shù)據(jù)庫操作全部依賴此對象。

注意:dataWithPath中的路徑參數(shù)一般會選擇保存到沙箱中的Documents目錄中;如果這個參數(shù)設置為nil則數(shù)據(jù)庫會在內(nèi)存中創(chuàng)建;如果設置為@””則會在沙箱中的臨時目錄創(chuàng)建,應用程序關閉則文件刪除。

2.對于數(shù)據(jù)庫的操作跟前面KCDbManager的封裝是類似的,在FMDB中FMDatabase類提供了兩個方法executeUpdate:和executeQuery:分別用于執(zhí)行無返回結(jié)果的查詢和有返回結(jié)果的查詢。

對于有返回結(jié)果的查詢而言,查詢完返回一個游標FMResultSet,通過遍歷游標進行查詢。而且FMDB中提供了大量intForColumn、stringForColumn等方法進行取值。

并發(fā)和事務

我們知道直接使用libsqlite3進行數(shù)據(jù)庫操作其實是線程不安全的,如果遇到多個線程同時操作一個表的時候可能會發(fā)生意想不到的結(jié)果。為了解決這個問題建議在多線程中使用FMDatabaseQueue對象,相比FMDatabase而言,它是線程安全的。

創(chuàng)建FMDatabaseQueue的方法是類似的,調(diào)用databaseQueueWithPath:方法即可。注意這里不需要調(diào)用打開操作。

然后所有的增刪改查操作調(diào)用FMDatabaseQueue的inDatabase:方法在block中執(zhí)行操作sql語句即可。

之所以將事務放到FMDB中去說并不是因為只有FMDB才支持事務,而是因為FMDB將其封裝成了幾個方法來調(diào)用,不用自己寫對應的sql而已。其實在在使用libsqlite3操作數(shù)據(jù)庫時也是原生支持事務的(因為這里的事務是基于數(shù)據(jù)庫的,F(xiàn)MDB還是使用的SQLite數(shù)據(jù)庫),只要在執(zhí)行sql語句前加上“begin transaction;”執(zhí)行完之后執(zhí)行“commit transaction;”或者“rollback transaction;”進行提交或回滾即可。另外在Core Data中大家也可以發(fā)現(xiàn),所有的增、刪、改操作之后必須調(diào)用上下文的保存方法,其實本身就提供了事務的支持,只要不調(diào)用保存方法,之前所有的操作是不會提交的。在FMDB中FMDatabase有beginTransaction、commit、rollback三個方法進行開啟事務、提交事務和回滾事務。

四 CoreData,sqlite3,F(xiàn)MDB 對比
4.1 Core Data
  1. core data 基于model-view-controller(mvc)模式下,為創(chuàng)建分解的cocoa應用程序提供了一個靈活和強大的數(shù)據(jù)模型框架。

  2. core data可以使你以圖形界面的方式快速的定義app的數(shù)據(jù)模型,同時在你的代碼中容易獲取到它。core data提供了基礎結(jié)構(gòu)去處理常用的功能,例如保存,恢復,撤銷和重做,允許你在app中繼續(xù)創(chuàng)建新的任務。在使用core data的時候,你不用安裝額外的數(shù)據(jù)庫系統(tǒng),因為core data使用內(nèi)置的sqlite數(shù)據(jù)庫。

  3. core data提供了一個通用的數(shù)據(jù)管理解決方案來處理那些所有需要數(shù)據(jù)模型的app(或大或小)。app使用core data來管理數(shù)據(jù)對象是很多的益處。

  4. core data將你app的模型層放入到一組定義在內(nèi)存中的數(shù)據(jù)對象。core data會追蹤這些對象的改變,同時可以根據(jù)需要做相反的改變,例如用戶執(zhí)行撤銷命令。當core data在對你app數(shù)據(jù)的改變進行保存的時候,core data會把這些數(shù)據(jù)歸檔,并永久性保存。它保存的數(shù)據(jù)在一些常規(guī)的文件,你可以在Finder中可以進行管理,用spotlight進行搜索,備份到 cd,和email給朋友或者家人。

  5. 在使用core data框架的時候,你可以創(chuàng)建一個管理對象的模型,該模型提供了對模型對象的抽象定義,這也就是我們所知道的entities,它可以在我們的程序中使用。

  6. core data是一個實體-關系模型,該模型是使用Xcode的數(shù)據(jù)模型設計工具來定義的,對數(shù)據(jù)實體以及他們的關系提供了豐富的環(huán)境。

4.2 sqlite

mac os x中sqlite庫,它是一個輕量級功能強大的關系數(shù)據(jù)引擎,也很容易嵌入到應用程序??梢栽诙鄠€平臺使用,sqlite是一個輕量級的嵌入式sql數(shù)據(jù)庫編程。與core data框架不同的是,sqlite是使用程序式的,sql的主要的API來直接操作數(shù)據(jù)表。

4.3 FMDB

FMDB框架是對sqlite很薄的封裝,主要的類也就兩個:FMDatabase和FMResultSet。在使用fmdb的時候還需要導入libsqlite3.0.dylib。

core data允許用戶使用代表實體和實體間關系的高層對象來操作數(shù)據(jù)。它也可以管理串行化的數(shù)據(jù),提供對象生存期管理與object_graph 管理,包括存儲。Core Data直接與Sqlite交互,避免開發(fā)者使用原本的SQL語句.

4.4 選擇
  1. 在編寫程序的時候盡量使用core data,這樣才是最優(yōu)的選擇。

  2. 至于sqlitefmdb的使用情況,這個看個人喜好。fmdb就是對sqlite的封裝,使用起來有方便的接口,沒那么麻煩而已。


本文參考
coreData,sqlite3,fmdb對比

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

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

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