介紹
realm是一個(gè)跨平臺(tái)移動(dòng)數(shù)據(jù)庫引擎,支持iOS辽故、OS X(Objective-C和Swift)以及Android。
2014年7月發(fā)布。由YCombinator孵化的創(chuàng)業(yè)團(tuán)隊(duì)歷時(shí)幾年打造翁潘,是第一個(gè)專門針對(duì)移動(dòng)平臺(tái)設(shè)計(jì)的數(shù)據(jù)庫。目標(biāo)是取代SQLite歼争。
為了徹底解決性能問題拜马,核心數(shù)據(jù)引擎C++打造,并不是建立在SQLite之上的ORM沐绒。如果對(duì)數(shù)據(jù)引擎實(shí)現(xiàn)想深入了解可以查看:Realm 核心數(shù)據(jù)庫引擎探秘俩莽。因此得到的收益就是比普通的ORM要快很多,甚至比單獨(dú)無封裝的SQLite還要快乔遮。
因?yàn)槭荗RM扮超,本身在設(shè)計(jì)時(shí)也針對(duì)移動(dòng)設(shè)備(iOS、Android),所以非常簡單易用出刷,學(xué)習(xí)成本很低璧疗。
吸引我的地方
- 首先是realm的速度,雖然一般的手機(jī)客戶端不會(huì)用到大數(shù)據(jù)的情況馁龟,但有些情況你還是會(huì)經(jīng)常遇到的崩侠。比如要存全國的省市區(qū),這個(gè)數(shù)據(jù)量就很大坷檩,而且還是關(guān)系型的却音。如果用coredata會(huì)灰常的慢,這個(gè)時(shí)候Realm就派上用場了矢炼。
- 其次是realm的使用系瓢,realm相對(duì)于coredata,不管是增刪改查裸删,還是數(shù)據(jù)庫版本的更新八拱,都要更加的簡單,比較適合新手使用涯塔,降低了團(tuán)隊(duì)學(xué)習(xí)的成本肌稻。
這里要說一下數(shù)據(jù)庫的版本更新,當(dāng)我們的數(shù)據(jù)庫中表的字段發(fā)生變化時(shí)匕荸,為了兼容老版本爹谭,需要對(duì)數(shù)據(jù)庫進(jìn)行升級(jí)。這個(gè)在coredata里是有的榛搔,但是需要操作的地方很多诺凡,既要在試圖里修改,還要重新生產(chǎn)實(shí)例践惑。但是realm就比較方便了腹泌,幾行代碼。而且如果改動(dòng)特別大尔觉,可以直接創(chuàng)建新的庫出來凉袱,比coredata要靈活。 - 最后realm發(fā)展到現(xiàn)在也相對(duì)比較成熟了侦铜,有團(tuán)隊(duì)專門去維護(hù)专甩,熱度也比較高,可以在一些功能上試用起來钉稍。
簡單的展示一下速度對(duì)比:
每秒能在20萬條數(shù)據(jù)中進(jìn)行查詢后count的次數(shù)涤躲。realm每秒可以進(jìn)行30.9次查詢后count。查詢速度要比coredata快30倍贡未,非持钟#恐怖蒙袍。
部署realm
說了這么多好處,現(xiàn)在開始實(shí)施缸托。首先我們要部署realm數(shù)據(jù)庫左敌,官網(wǎng)上介紹了四種部署方式:
1.加入動(dòng)態(tài)庫2.通過cocoapods3.通過carthage4.加靜態(tài)庫
這里我用的是cocoapods,直接在podfile中加一句話:
pod 'Realm'
然后pod update 俐镐,庫比較大矫限,時(shí)間會(huì)有點(diǎn)長。
realm基本操作
數(shù)據(jù)庫操作大概就是增刪改查佩抹,接下來我會(huì)以這個(gè)分為四大塊來逐一介紹
創(chuàng)建model
#import "CityEntity.h"
#import <Realm/Realm.h>
RLM_ARRAY_TYPE(CityEntity)
@interface ProvinceEntity : RLMObject
@property NSString *enName;
@property int pid;
@property NSString *prefixLetter;
@property NSString *shortName;
@property int sId;
@property int type;
@property RLMArray<CityEntity *><CityEntity> *citys;
@end
這樣就創(chuàng)建好了一個(gè)數(shù)據(jù)模型叼风,可以對(duì)比一下coredata的數(shù)據(jù)模型,明顯簡潔了:
- 不要去聲明屬性的類型棍苹,原子性无宿,強(qiáng)弱類型都不需要指定
- 支持int類型,coredata中的int 只能轉(zhuǎn)為nsnumber
這里要注意的是枢里,如果需要設(shè)置一對(duì)多的關(guān)系孽鸡,需要兩個(gè)步驟:
- 1.首先申明RLM_ARRAY_TYPE(CityEntity),這句話的作用是申明一個(gè)RLMArray<CityEntity> type栏豺。這個(gè)申明可以放在兩個(gè)地方彬碱,一個(gè)是你需要關(guān)聯(lián)的那個(gè)類的最上方,就像我現(xiàn)在寫的這樣奥洼,放在ProvinceEntity上方巷疼。你也可以放在CityEntity的最后,也就是@end下方灵奖。如同這樣:
#import "AreaEntity.h"
#import <Realm/Realm.h>
RLM_ARRAY_TYPE(AreaEntity)
@interface CityEntity : RLMObject
@property NSString *enName;
@property int pid;
@property NSString *prefixLetter;
@property NSString *shortName;
@property int sId;
@property int type;
@property RLMArray<AreaEntity *><AreaEntity> *areas;
//@property ProvinceEntity *inProvince;
@end
RLM_ARRAY_TYPE(CityEntity)
- 2.然后增加關(guān)聯(lián)的屬性@property RLMArray<CityEntity *><CityEntity> *citys;
RLMArray<CityEntity *><CityEntity> * citys 這樣申明看著有點(diǎn)怪怪的嚼沿,拆為三部分來看
RLMArray,這個(gè)沒什么好說瓷患,就是數(shù)組類型
<CityEntity *>官方解釋屬性的特別化(generic specialization)骡尽,這可以阻止在編譯時(shí)使用錯(cuò)誤對(duì)象類型的數(shù)組。
<CityEntity>這個(gè)其實(shí)和RLMArray是連在一起的擅编, 此RLMArray遵守的協(xié)議爆阶,可以讓 Realm 知曉如何在運(yùn)行時(shí)確定數(shù)據(jù)模型的架構(gòu)。
新增數(shù)據(jù)
首先要造好數(shù)據(jù)(展示關(guān)鍵代碼):
ProvinceEntity* province=[[ProvinceEntity alloc] init];
//...賦值
CityEntity *city = [[CityEntity alloc] init];
[province.citys addObject:city];
其實(shí)有三種創(chuàng)建方式:
// (1) Create a Dog object and then set its properties
Dog *myDog = [[Dog alloc] init];myDog.name = @"Rex";myDog.age = 10;
// (2) Create a Dog object from a dictionary
Dog *myOtherDog = [[Dog alloc] initWithValue:@{@"name" : @"Pluto", @"age" : @3}];
// (3) Create a Dog object from an array
Dog *myThirdDog = [[Dog alloc] initWithValue:@[@"Pluto", @3]];
然后把記錄插入到數(shù)據(jù)庫中:
// Get the default Realm
RLMRealm *realm = [RLMRealm defaultRealm];
// You only need to do this once (per thread)
// Add to Realm with transaction
[realm beginWriteTransaction];
[realm addObject:province];
[realm commitWriteTransaction];
查詢數(shù)據(jù)
如果用過coredata沙咏,那你一定對(duì)NSPredicate會(huì)很熟悉。Realm即支持NSPredicate也支持?jǐn)嘌宰址樵儼嗵祝@樣從coredata遷移過來的話肢藐,之前的查詢語句就不用修改,直接沿用即可:
// 使用斷言字符串查詢
RLMResults<ProvinceEntity *> *provinceArray = [ProvinceEntity objectsWhere:@"shortName = '江蘇'"];
// 使用 NSPredicate 查詢
NSPredicate *pred = [NSPredicate predicateWithFormat:@"shortName = '江蘇'"];
provinceArray = [ProvinceEntity objectsWithPredicate:pred];
如果有多條件的話吱韭,可以用and吆豹,也可以分布查詢鱼的,從查詢結(jié)果中再做查詢,支持鏈?zhǔn)讲樵儯?/p>
RLMResults<Dog *> *tanDogs = [Dog objectsWhere:@"color = '棕黃色'"];RLMResults<Dog *> *tanDogsWithBNames = [tanDogs objectsWhere:@"name BEGINSWITH '大'"];
RLMResults允許您指定一個(gè)排序標(biāo)準(zhǔn)痘煤,從而可以根據(jù)一個(gè)或多個(gè)屬性進(jìn)行排序凑阶。比如說,下列代碼將上面例子中返回的狗狗根據(jù)名字升序進(jìn)行排序:
// 排序名字以“大”開頭的棕黃色狗狗
RLMResults<Dog *> *sortedDogs = [[Dog objectsWhere:@"color = '棕黃色' AND name BEGINSWITH '大'"] sortedResultsUsingProperty:@"name" ascending:YES];
更新數(shù)據(jù)
這里要吐槽一下coredata的更新衷快,coredata沒有更新宙橱,要想完成更新的操作只能先查再刪,灰常麻煩蘸拔,效率也低师郑。realm就要好很多,他支持更新调窍。
- 你可以找到具體的一條數(shù)據(jù)然后去更新:
RLMResults<ProvinceEntity *>* provinceArray=[ProvinceEntity allObjects];
[[RLMRealm defaultRealm] transactionWithBlock:^{
ProvinceEntity *province=[provinceArray firstObject];
province.shortName=@"浙江";
}];
- 你也可以設(shè)置一個(gè)主鍵宝冕,根據(jù)主鍵去更新,更新需要擁有一個(gè)主鍵---Primary Keys:
@implementation Person
+ (NSString *)primaryKey {
return @"id";
}
@end
然后通過realm提供的接口:
// Creating a book with the same primary key as a previously saved
bookBook *cheeseBook = [[Book alloc] init];
cheeseBook.title = @"Cheese recipes";
cheeseBook.price = @9000;
cheeseBook.id = @1;
// Updating book with id = 1
[realm beginWriteTransaction];
[realm addOrUpdateObject:cheeseBook];
[realm commitWriteTransaction];
刪除數(shù)據(jù)
刪除數(shù)據(jù)分為三種:
- 單條記錄刪除:
// Delete an object with a transaction
[realm beginWriteTransaction];
[realm deleteObject:cheeseBook];
[realm commitWriteTransaction];
- 多條記錄刪除:
// Delete an object with a transaction
[[RLMRealm defaultRealm] transactionWithBlock:^{
[[RLMRealm defaultRealm] deleteObjects:result];
}];
- 全部刪除:
// Delete an object with a transaction
[[RLMRealm defaultRealm] transactionWithBlock:^{
[[RLMRealm defaultRealm] deleteAllObjects];
}];
總結(jié)
realm作為一款跨平臺(tái)的數(shù)據(jù)庫邓萨,首先兼容性就比較好地梨。就ios而言,oc和swift都支持缔恳。性能又非常的強(qiáng)勁宝剖,速度很快。上面介紹了realm的基本操作褐耳,可以看到realm使用起來是非常簡單的诈闺,而且他已經(jīng)幫你把事務(wù)做好了。這就保證了realm在實(shí)際使用中的安全性铃芦,不會(huì)因?yàn)橐恍┩话l(fā)情況造成數(shù)據(jù)的紊亂雅镊。之后我會(huì)對(duì)他進(jìn)行更深入的探討,如果你感興趣可以關(guān)注我刃滓。
參考:
感謝下面文章的作者:
http://www.cocoachina.com/ios/20160513/16241.html
感謝官網(wǎng):
https://realm.io/