從0開始弄一個面向OC資料庫--終結篇

___發表於2017-12-27

前言

我們從0開始封了一個面向OC模型的資料庫就要結束了,開發工作其實在上一篇就做完了,之後做了一些小的優化以及程式碼的調整來發布這篇文章,先看一下我們最終形態。

  • 直接: 呼叫sqlite原生API運算元據庫,沒有中間框架。
  • 易用: 一行程式碼實現資料庫增刪查改操作。
  • 多元: 支援所有基本資料型別、集合型別以及自定義模型。
  • 智慧: 一行程式碼,智慧實現插入、更新、升級、遷移資料。
  • 強大: 0程式碼支援陣列巢狀模型、巢狀字典,字典巢狀模型等相互巢狀。
  • 靈活: 支援多種查詢、刪除操作,支援使用sql語句查詢、刪除。
  • 還原: 存入資料庫時為A模型,查詢的資料一定還給你A模型。

我們支援的型別有

所有的基本資料型別(int,float),NSNumber,NSArray,NSMutableArray,NSDictionary,NSMutableDictionary,
UIImage,NSURL,UIColor,NSSet,NSRange,NSAttributedString,NSData,自定義模型,以及陣列、字典、模型相互巢狀
複製程式碼

從0開始弄一個面向OC資料庫--終結篇

這篇文章,將全方位介紹我們資料庫--CWDB以及如何使用!

架構

類名 作用
CWModelProtocol.h 需要遵守以及實現的協議方法(使用者關注)
CWSqliteModelTool.h、CWSqliteModelTool.m 本庫運算元據庫的所有API(使用者關注)
CWDatabase.h、CWDatabase.m 直接呼叫sqlite底層API的類
CWModelTool.h、CWModelTool.m 處理模型的工具類
CWSqliteTableTool.h、CWSqliteTableTool. 處理資料庫表的工具類

在使用前,我們先模擬一個對應的使用場景,要解決什麼問題,這個場景也是我們demo中的演示程式碼所展現的(你可以開啟demo在Clasess目錄下找到它)。

我們希望儲存幾所學校的資料到資料庫。

  • 用一個類來表示學校的資料,資料有學校id,名字,整個學校的所有班級,最好的班級,最優秀的老師的資料。
  • 有對應類來表示班級的資料,班級裡面有班級號,名稱,班級的所有老師,班級的所有學生,班主任以及班長。
  • 又分別有兩個類儲存學生和老師的資料

以上的層級關係有模型巢狀陣列巢狀模型的場景、模型巢狀模型再巢狀資料再巢狀模型的場景也就模型直接巢狀模型的場景。

然後我們使用工廠方法來快速構造各個模型,用來搭建整個學校

  • 首先,所有的學生都是身高168,年齡20,體重100,性格溫和乖巧的女同學
  • 其次,所有的老師都是身高155,年齡28,體重100的御姐老師
  • 再次,我給每個班級新增5名鬆島?同學,2名林?玲老師以及一位蒼老師班主任
  • 最後,我任命我為全校唯一男人+校長,我在學校裡面開設了2種專業總共4個班級,1個技巧班,3個聲音班。保齡球玩得溜的關?琳同學獲得最優學生,技巧班為最優班級,最好的老師當然是傳授身教的蒼老師

學校的結構設定好了之後~我們用程式碼構造一所所這樣的夢想學院。。然後我們要使用我們的資料庫將學校的資料儲存起來。

How to use CWDB?

1、將CWDB拖進你的專案或者使用cocoapods(pod ‘CWDB’, '~> 1.5.0’),給專案新增sqlite3.0.tbd庫,需要儲存進資料庫的模型匯入CWModelProtocol.h標頭檔案,然後遵守CWModelProtocol協議,實現下面這個方法返回對應的主鍵資訊:

+ (NSString *)primaryKey {
    // 返回schoolId為主鍵
    return @"schoolId";
}
複製程式碼

2、為所欲為之為所欲為運算元據庫

  • 插入或者更新資料
// 使用工廠方法建立的shool模型
CWSchool *school = [self cwSchoolWithID:9999 name:@"夢想學院"];
    
// 呼叫儲存或者更新方法,uid為userId,對應資料庫的名字,targetId為目標ID,與資料庫表名相關,可以傳nil。
BOOL result = [CWSqliteModelTool insertOrUpdateModel:school uid:nil targetId:nil];
複製程式碼

為什麼要設定兩個多餘的引數uid與TargetId?為了迎合下面一些場景,如果你不關注,傳nil即可

  • uid:在做IM的時候,一個手機APP可能登陸不同的賬號,這個時候,我們希望將不同賬號的資訊,分為不同的資料庫去儲存,比如張三登陸了,我們以張三.db 新建一個資料庫(之前沒有資料庫的情況下),李四登陸了,我們再以李四.db 新建一個資料庫,他們的資訊分別存在自己的資料庫裡,這樣設計有什麼好處?我們可以把各個使用者的聊天記錄以及相關資訊分別儲存,方便管理以及查詢,比如你去銀行存錢,你的錢一定是存在你的銀行卡里面,而不會是你、我、他的錢都存在同一個銀行卡里面,所以我們這裡要傳uid,用來分辨是哪一個使用者的資料庫。如果不傳,會預設為CWDB公共資料庫。
  • targetId:首先我們要說明,我們資料庫的表名是以模型型別的名稱來命名的。在大部分情況下,僅僅這樣是沒有問題的,但是,同樣是在IM的場景下,比如我和張三聊天,那麼我和張三的聊天記錄會以Message的模型存在Message的表裡面,如果我和李四聊天,那麼我和李四的聊天記錄也存在Message的表裡面嗎?這樣資料庫的資料會非常混亂,因為你可能會和更多的人聊天,那Message這個表會非常臃腫,所以我們引入targetId目標ID這一引數,我們的表名就會是《模型名稱+targetId》,以張三為例,他的聊天記錄表就是Message張三,李四就是Message李四。如果你的資料庫裡面一個模型只需要統一管理一個表,那麼你傳nil即可。

關於資料庫升級以及資料庫遷移,假設我存在資料庫的資料為聊天記錄Message,裡面有10個成員變數,有一天,業務的提升,我要在Message裡面多加一個成員變數,如新增一個成員變數用來標記是否是撤回的訊息,這個時候由於資料庫的表結構固定死了沒這個欄位,插入資料肯定是失敗的,為了解決這個問題,我們將要進行資料庫升級,並且要將之前的資料都保留下來,這個要怎麼做呢?這裡壓根不需要你思考這個問題,我作為一個負責任的男人,我很負責任的告訴你,假如你的Message模型新增加了1個2個10個成員變數,你只管加,加了之後只管呼叫上面的方法存,資料的升級以及遷移我們預設會幫你完成!!!

  • 查詢所有資料
// result內的元素為CWSchool的模型
NSArray *result = [CWSqliteModelTool queryAllModels:[CWSchool class] uid:nil targetId:nil];
複製程式碼

查詢方法返回值是一個陣列,這個陣列裡面的資料全部為CWSchool的模型,因為我們承諾過,儲存的時候是模型A,查詢出來的一定也是模型A。

  • 刪除資料
CWSchool *school = [self cwSchoolWithID:9999 name:@"夢想學院"];
// 刪除school資料
BOOL result = [CWSqliteModelTool deleteModel:school uid:nil targetId:nil];
複製程式碼

這個方法,會根據傳進來的模型的主鍵值去找到資料表裡面的資料刪除。

我們的功能基本都在這了,除了還有一些條件查詢與刪除沒寫在這裡。有人會問,資料庫不是增刪查改4個嗎?怎麼你只有3個,我們也實現了改的操作,只是我們把這個操作和增合併成了一個方法,也就是這裡的第一個方法,我們會根據主鍵來判斷資料庫內是否存在對應的資料,如果存在,我們則進行更新操作,不存在則插入資料。

我們的演示程式碼對資料庫操作提供了一個視覺化的操作介面,大概是這樣子

從0開始弄一個面向OC資料庫--終結篇
當然插入的資料與查詢的資料是否對應從介面上是無法看出來的,你可以像我這樣打一個斷點檢視

從0開始弄一個面向OC資料庫--終結篇

關於CWDB的更多用法,請轉到github:CWDB檢視或者看程式碼提供的API。。如果有不能滿足你需求的場景或者有任何疑問,歡迎留言或者提issue,最終看在全校女同學的面子上 give me one star !!

如果你也想封裝一個有很多女同學的資料庫,但是沒有資料學的話,可以前往我之前文章的傳送門,每個功能的實現,我們都提供了非常詳細的講解:

從0開始弄一個面向OC資料庫(一)

從0開始弄一個面向OC資料庫(二)

從0開始弄一個面向OC資料庫(三)

從0開始弄一個面向OC資料庫(四)

從0開始弄一個面向OC資料庫(五)

相關文章