iOS-FMDB改進方案YIIFMDB:直接操作Model盆佣,純面向對象,不需要寫sql語句

我在寫UDUserDefaultsModel(文章鏈接,github)這個庫時曾經立下一個flag:要寫一個基于model來存取數(shù)據(jù)庫的庫械荷,最近剛離職共耍,所以就整合了一下,希望大家多多支持吨瞎。

在iOS開發(fā)過程當中痹兜,難免用到數(shù)據(jù)庫,以FMDB居多颤诀。以下是一個根據(jù)年齡篩選數(shù)據(jù)的sql語句:

select * from Student where age > 10 and age < 20 or age > 30 order by age desc limit 20

這樣寫其實沒什么問題字旭,但是在我個人看來難以接受,字符串看起來太別扭崖叫。比如我再添加一個條件遗淳,那么就需要修改整個字符串了。

如果可以很好的控制sql語句心傀,將大大提高編程效率屈暗。為此,YIIFMDB就改善了這個缺陷:純面向對象脂男,直接操作Model养叛,完全不需要寫sql語句

其靈感源自于php的Yii 2架構宰翅,因為我在看php代碼當中弃甥,我發(fā)現(xiàn)根本就看不到sql語句,而php程序猿也說:“我們的工作就是操作數(shù)據(jù)庫堕油,但是卻不寫sql語句”潘飘。

以下是YIIFMDB詳細用法:
YIIFMDB有兩個類:YIIFMDB和YIIParameters。其中YIIFMDB封裝了數(shù)據(jù)庫相關的操作掉缺,比如增刪改查之類卜录,而YIIParameters則封裝了where之后的參數(shù),比如上段代碼當中的:

age > 10 and age < 20 or age > 30 order by age desc limit 20

就可以在YIIParameters當中完成眶明。

接下來逐一介紹YIIParameters類和YIIFMDB類的使用:

YIIParameters類

sql語句當中where之后的參數(shù)基本上由以下模塊構成:

  • and(與操作)
  • or(或操作)
  • order by(排序)
  • limit(數(shù)量限制)

其中的andor又要配置“>,<,=,>=,<=,!=,like”關系艰毒,order by又有“ase,dese”的排序操作搜囱。

YIIParameters這個類就包含了以上所有元素丑瞧。以上面的where之后的sql語句為例柑土,具體用法如下:

// 初始化YIIParameters
YIIParameters *parameters = [[YIIParameters alloc] init];
// 執(zhí)行and操作,將age限制在10-20之間
// age > 10,YIIParametersRelationTypeGreaterThan標志">"
[parameters andWhere:@"age" value:@"10" relationType:YIIParametersRelationTypeGreaterThan];  
// age < 20,YIIParametersRelationTypeLessThan標志"<"
[parameters andWhere:@"age" value:@"20" relationType:YIIParametersRelationTypeLessThan];
// 以上是and绊汹,也就是形成的sql語句為: age > 10 and age < 20
// 執(zhí)行or操作稽屏,將age限制在age > 30 以上
[parameters orWhere:@"age" value:@"30" relationType:YIIParametersRelationTypeGreaterThan];
// 根據(jù)age進行降序排列
// YIIParametersOrderTypeDesc表示降序"desc",YIIParametersOrderTypeAsc
[parameters orderByColumn:@"age" orderType:YIIParametersOrderTypeDesc];
// 將數(shù)據(jù)的個數(shù)限制在20個
parameters.limitCount = 20;

配置完畢,驗證其是否配置正確西乖,那么可以調用一下方法就行了:

NSLog(@"where參數(shù)為:%@", parameters.whereParameters);

當然狐榔,如果參數(shù)都沒法配置了,則可以設置whereParameters获雕。而對于YIIParameters更詳細的解釋請參考 YIIFMDB中的YIIParameters.h薄腻。

YIIFMDB

YIIParameters用來配置sql語句當中where之后的參數(shù),而YIIFMDB類則是對數(shù)據(jù)庫操作的進一步封裝届案,具體如下:

獲取YIIFMDB單例

YIIFMDB *db = [YIIFMDB shareDatabase]; // 推薦使用
// 或者
YIIFMDB *db = [YIIFMDB shareDatabaseForName:@"ABC.sqlite" path:path]; // 自定義數(shù)據(jù)庫名字和路徑庵楷,在第一次實例的時候傳入,以后使用上面方法即可楣颠。

主鍵的字段

@property (nonatomic, readonly, copy) NSString *primaryKey; // 返回"yii_pkID",我自己在創(chuàng)建數(shù)據(jù)庫是配置的主鍵字段

是否打印log

@property (nonatomic, assign) BOOL shouldOpenDebugLog; // 默認為NO尽纽,設為YES,會在控制器后臺打印數(shù)據(jù)庫操作相關的一些信息

創(chuàng)建一張表

[[YIIFMDB shareDatabase] createTableWithModelClass:[LCPersonModel class] excludedProperties:nil tableName:@"Person"];

此方法是創(chuàng)建一張名為@"Person"表童漩,并且蜓斧,表里面的字段也就是LCPersonModel里面的屬性,字段的數(shù)據(jù)類型也對應LCPersonModel里面的數(shù)據(jù)類型

插入一條數(shù)據(jù)(增)

  LCPersonModel *model = [[LCPersonModel alloc] init];
  model.name = [NSString stringWithFormat:@"lc%d", (arc4random() % 100)];
  model.gender = arc4random() % 2;
  model.age = arc4random() % 80;
  model.floatNumber = (arc4random() % 20) / 100.0;
  model.doubleNumber = (arc4random() % 20) / 100.0;
  model.isMan = arc4random() % 2;
  model.number = @(arc4random() % 10);
            
  YIIFMDB *db = [YIIFMDB shareDatabase];
  BOOL isSuccess = [db insertWithModel:model tableName:tableName];  //插入一條數(shù)據(jù)
  [db insertWithModels:@[model] tableName:tableName];     // 批量插入數(shù)據(jù)

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

-(BOOL)deleteFromTable:(NSString * _Nonnull)tableName whereParameters:(YIIParameters *)parameters; // 根據(jù)參數(shù)刪除一條數(shù)據(jù),YIIParameters參考上面
-(BOOL)deleteAllDataFromTable:(NSString * _Nonnull)tableName; // 刪除表中的所有數(shù)據(jù)

 YIIFMDB *db = [YIIFMDB shareDatabase];
 YIIParameters *parameters = [[YIIParameters alloc] init];
 // db.primaryKey 是數(shù)據(jù)庫的主鍵,這條語句意思是刪除主鍵 = 1的那條數(shù)據(jù)
 [parameters andWhere:db.primaryKey value:@"1" relationType:YIIParametersRelationTypeEqualTo];
 [db deleteFromTable:tableName whereParameters:parameters];

更改數(shù)據(jù)(改)

-(BOOL)updateTable:(NSString * _Nonnull)tableName dictionary:(NSDictionary * _Nonnull)dictionary whereParameters:(YIIParameters *)parameters; // 更新一條數(shù)據(jù)

  YIIFMDB *db = [YIIFMDB shareDatabase];
  YIIParameters *parameters = [[YIIParameters alloc] init];
  // 參數(shù)設置為主鍵 = 10
  [parameters andWhere:db.primaryKey value:@"10" relationType:YIIParametersRelationTypeEqualTo];
  // 將主鍵為10的那條數(shù)據(jù)的name更改為monkey
  [db updateTable:tableName dictionary:@{@"name": @"monkey"} whereParameters:parameters];

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

-(NSArray *)queryFromTable:(NSString * _Nonnull)tableName model:(Class _Nonnull)modelClass whereParameters:(YIIParameters *)parameters; // 根據(jù)YIIParameters條件從表為tableName的查詢數(shù)據(jù)

  YIIFMDB *db = [YIIFMDB shareDatabase];
  YIIParameters *parameters = [[YIIParameters alloc] init];
  [parameters andWhere:db.primaryKey value:@"5" relationType:YIIParametersRelationTypeLessThan];
  NSLog(@"主鍵小于5的數(shù)據(jù):%@", [db queryFromTable:tableName model:[LCPersonModel class] whereParameters:parameters]);

除了增刪改查之外睁冬,YIIFMDB還提供了增加一個屬性挎春,刪除一張表,獲取表中所有字段名豆拨,獲取表中數(shù)據(jù)個數(shù)直奋,表是否存在,求和施禾,求平均值脚线,最大值,最小值等功能弥搞,詳情請參考YIIFMDB的文檔邮绿。

線程安全操作(隊列和事務)

由于FMDB本身就是是不安全的,上面的方法也是不安全的,為了保證其安全則需要結合隊列和事務操作,參考FMDB的隊列和事務译柏。

-(void)inDatabase:(dispatch_block_t)block; // 將數(shù)據(jù)庫相關操作寫在block里可保證線程安全

  YIIFMDB *db = [YIIFMDB shareDatabase];
   [db inDatabase:^{
       // 增刪改查放在此代碼塊里執(zhí)行則可以保證線程安全
   }];

-(void)inTransaction:(void(^)(BOOL *rollback))block; // 在block里寫入代碼可執(zhí)行回滾操作

  YIIFMDB *db = [YIIFMDB shareDatabase];
  [db inTransaction:^(BOOL *rollback) {
  // 如果某一個操作失誤炫七,則可以執(zhí)行回滾操作
  BOOL isSuccess = YES;   // 數(shù)據(jù)庫操作是否操作成功
  if (!isSuccess) {
      *rollback = YES;  //  回滾操作
                    
      return ;
     }
  }];

這里還有兩個缺陷:

  • 未支持聯(lián)表查詢
  • 未支持Model當中套Model的插入观蜗。

如果是聯(lián)表查詢的話,那么需要獲取到YIIFMDB單例的"currentDatabase"來實現(xiàn)聯(lián)表查詢持搜,而Model套Model的备韧,則最好是創(chuàng)建兩張表酱鸭。

目前YIIFMDB已支持Cocoapods吗垮,地址:Github。(不要吝嗇你的star)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末凹髓,一起剝皮案震驚了整個濱河市烁登,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蔚舀,老刑警劉巖防泵,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蝗敢,居然都是意外死亡,警方通過查閱死者的電腦和手機足删,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門寿谴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人失受,你說我怎么就攤上這事讶泰。” “怎么了拂到?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵痪署,是天一觀的道長。 經常有香客問我兄旬,道長狼犯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任领铐,我火速辦了婚禮悯森,結果婚禮上,老公的妹妹穿的比我還像新娘绪撵。我一直安慰自己瓢姻,他們只是感情好,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布音诈。 她就那樣靜靜地躺著幻碱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪细溅。 梳的紋絲不亂的頭發(fā)上褥傍,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機與錄音喇聊,去河邊找鬼摔桦。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的邻耕。 我是一名探鬼主播鸥咖,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼兄世!你這毒婦竟也來了啼辣?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤御滩,失蹤者是張志新(化名)和其女友劉穎鸥拧,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體削解,經...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡富弦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了氛驮。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腕柜。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖矫废,靈堂內的尸體忽然破棺而出盏缤,到底是詐尸還是另有隱情,我是刑警寧澤蓖扑,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布唉铜,位于F島的核電站,受9級特大地震影響律杠,放射性物質發(fā)生泄漏潭流。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一柜去、第九天 我趴在偏房一處隱蔽的房頂上張望幻枉。 院中可真熱鬧,春花似錦诡蜓、人聲如沸熬甫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽椿肩。三九已至,卻和暖如春豺谈,著一層夾襖步出監(jiān)牢的瞬間郑象,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工茬末, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留厂榛,地道東北人盖矫。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像击奶,于是被迫代替她去往敵國和親辈双。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345