Realm 移動端數(shù)據(jù)庫
- 首先簡單介紹一下Realm
移動端跨平臺數(shù)據(jù)庫,相較于CoreData、FMDB等數(shù)據(jù)持久化方案,Realm的使用更加方便,且上手更快,可利用Realm Browser軟件查看,底層不同于SQLite,是基于C++開發(fā)的存儲引擎。(官方文檔可以更好的了解)
1.Realm是一個類MVCC(多版本并發(fā)控制技術)數(shù)據(jù)庫,每個連接的線程在特定的時刻都有一個數(shù)據(jù)庫的快照。MVCC在設計上采用了和Git一樣的源文件管理算法,也就是說你的每個連接線程就好比在一個分支(也就是數(shù)據(jù)庫的快照)上工作,但是你并沒有得到一個完整的數(shù)據(jù)庫拷貝。Realm和一些真正的MVCC數(shù)據(jù)庫如MySQL是不同的,Realm在某個時刻只能有一個寫操作,且總是操作最新的數(shù)據(jù)版本,不能在老版本操作。
2.Realm的底層是用B+樹實現(xiàn),很多的文件系統(tǒng)都在使用它做元數(shù)據(jù)索引,n叉樹,n棵子樹的結點中含有n個關鍵字,每個關鍵字不保存數(shù)據(jù),只用來索引,所有數(shù)據(jù)都保存在葉子節(jié)點。
所以,Realm使每一個連接的線程都會有數(shù)據(jù)在一個特定時刻的快照,同時寫入過程也不用加鎖,也就解決了數(shù)據(jù)庫的并發(fā)問題。
3.Realm 是 SQLite 和 Core Data 的替代者,得益于其零拷貝的設計,幾乎沒有內(nèi)存開銷,因為每一個 Realm 對象直接通過一個本地 long 指針和底層數(shù)據(jù)庫對應,這個指針是數(shù)據(jù)庫中數(shù)據(jù)的鉤子。通常的數(shù)據(jù)庫中,我們查詢請求會轉(zhuǎn)化為一系列的sql語句,創(chuàng)建一個數(shù)據(jù)庫連接,再通過內(nèi)部的查詢優(yōu)化完成對應的查詢工作,讀取磁盤上的數(shù)據(jù)庫文件,返回這些內(nèi)容并存儲在內(nèi)存中,最后轉(zhuǎn)換為我們可使用的格式或者類型。
4.對于零拷貝設計,主要是數(shù)據(jù)庫文件通過Memory-mapped, Memory – mapped I/O 就是把磁盤上的file 映射到內(nèi)存中,當我們從內(nèi)存上獲取相應字節(jié)時,對應的file就會被讀取,同樣,我們在內(nèi)存上存儲字節(jié)時,對應的file就會被寫入,我們也就不需要通過read,write系統(tǒng)調(diào)用去操作I/O。Realm 允許文件在沒有做反序列化的情況下直接從內(nèi)存讀取,這樣大大提高了讀取效率。
對Realm架構更多感興趣的可參閱以上文章,本文不做贅述。
Realm數(shù)據(jù)庫 從入門到“放棄”
iOS學習筆記(11)-Realm初探
很感謝以上兩篇文章的作者,對當時初識realm的我?guī)椭艽蟆?/p>
Realm的安裝
- 推選cocoapods 簡單方便,便于管理
在項目的Podfile中,添加pod 'Realm',在終端運行pod install。
目前使用2.9.1版本 最新3.0.0測試版
Realm基礎使用
對于數(shù)據(jù)庫,首先就是建庫,建表。對比SQLite,通過一系列SQL語句完成,我們來看看realm中如何操作。
- 建庫
默認數(shù)據(jù)庫
通過調(diào)用 [RLMRealm defaultRealm] 來初始化以及訪問 realm變量。
存在于Documents (iOS) 或者 Application Support (OS X)文件夾下的一個名為“default.realm”的文件
數(shù)據(jù)庫配置
通過 RLMRealmConfiguration 來處理
+ (void)setDefaultRealmForUser:(NSString *)username {
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
// 使用默認的目錄,但是使用用戶名來替換默認的文件名
config.fileURL = [[[config.fileURL URLByDeletingLastPathComponent]
URLByAppendingPathComponent:username]
URLByAppendingPathExtension:@"realm"];
// 將這個配置應用到默認的 Realm 數(shù)據(jù)庫當中
[RLMRealmConfiguration setDefaultConfiguration:config];
}
- 建表
對于Realm而言,建表其實就是創(chuàng)建模型類,通過繼承 RLMObject 或者一個已經(jīng)存在的模型類,您就可以創(chuàng)建一個新的 Realm 數(shù)據(jù)模型對象。Realm模型對象在形式上基本上與其他 Objective?C 對象相同。

存儲字段對應類屬性
支持的數(shù)據(jù)類型有BOOL、bool、int、NSInteger、long、long long、float、double、NSString、NSDate、NSData 以及 被特殊類型標記的 NSNumber,注意:Realm不支持auto_increment類型
m文件中可設置可空屬性(Optional Properties),屬性特性(attributes),索引屬性(Indexed Properties),屬性默認值,對象的自更新特性,忽略屬性。詳細可見官方文檔
此處僅介紹下主鍵(Primary Keys)
重寫 [+primaryKey] 屬性id 作為主鍵
+ (NSString *)primaryKey {
return @"id";
}
設置主鍵之后,對象的更新更加高效,查詢速度更快,保持唯一性。 一旦帶有主鍵的對象被添加到 Realm 之后,該對象的主鍵將不可修改。
同時,RLMObject 能夠借助 RLMObject 以及 RLMArray屬性來和另一個 RLMObject 建立關系,一對一,一對多關系。
// Dog.h
@interface Dog : RLMObject
// 其余屬性聲明...
@property Person *owner;
@end
//Dog.h
@interface Dog : RLMObject// 屬性聲明...
@end
RLM_ARRAY_TYPE(Dog) // 定義一個 RLMArray<Dog> 類型,宏創(chuàng)建了一個協(xié)議,從而允許 RLMArray<Dog> 語法的使用。
// Person.h
@interface Person : RLMObject// 其余的屬性聲明...
@property RLMArray<Dog *><Dog> *dogs;
@end
Realm數(shù)據(jù)庫操作
- 增
對數(shù)據(jù)的存儲,其實就是對該對象的存儲,對對象的所有更改(添加,修改和刪除)都必須通過寫入事務(transaction)完成。Realm 的寫入操作是同步的,阻塞的,所以重復寫入是不會產(chǎn)生競爭條件的。
注意:在存儲數(shù)據(jù)之前,必須要對對象賦值。
Person *author = [[Person alloc] init];
author.name = @“JasonLee”;
// 獲取默認的 Realm 實例
RLMRealm *realm = [RLMRealm defaultRealm];
// 通過事務將數(shù)據(jù)添加到 Realm 中
[realm beginWriteTransaction];
[realm addObject:author];
[realm commitWriteTransaction];
- 刪
通過在寫入事務中將要刪除的對象傳遞給 -[RLMRealm deleteObject:] 方法,即可完成刪除操作。
刪除存儲在 Realm 中的所有數(shù)據(jù)并不會使Realm 文件的大小改變,因為它會保留空間以供日后快速存儲數(shù)據(jù)。
// 在事務中刪除一個對象
[realm beginWriteTransaction];
[realm deleteObject:xxx];//實例對象
[realm deleteAllObjects]; // 從 Realm 中刪除所有數(shù)據(jù)
[realm commitWriteTransaction];
事務操作也可以用:
[realm transactionWithBlock:^{
[realm deleteObject:cheeseBook];
[realm deleteAllObjects];
}];
- 改
對數(shù)據(jù)的修改,可以通過對其屬性值直接更新(同增),或者通過主鍵更新(當然,前提是你必須設置主鍵)。
Person *author = [[Person alloc] init];
author.name = @“JasonLee;
author.id = @007;
// 通過 id = 007 更新
[realm beginWriteTransaction];
[Person createOrUpdateInRealm:realm withValue:author];
[realm commitWriteTransaction];
增加也可以使用該方法,如果數(shù)據(jù)庫不存在該主鍵對象,將進行新增操作添加到數(shù)據(jù)庫。
- 查
查詢默認數(shù)據(jù)庫:[類名 allObjects],返回類的所有對象
返回類型為RLMResults
查詢指定數(shù)據(jù)庫:
// 查詢指定的 Realm 數(shù)據(jù)庫
RLMRealm *xxxrealm = [RLMRealm realmWithPath:@”xxx.realm"];
// 獲得一個指定的 Realm 數(shù)據(jù)庫
RLMResults *allXXX = [類名 allObjectsInRealm:xxxrealm];
條件查詢: 斷言+ 謂詞
1.使用斷言字符串查詢:
RLMResults *tanDogs = [Dog objectsWhere:@"color = '棕黃色' AND name BEGINSWITH '大'"];
2.// 使用 NSPredicate 查詢
NSPredicate *pred = [NSPredicate predicateWithFormat:@"color = %@ AND name BEGINSWITH %@”,@"棕黃色", @"大"];
RLMResults *tanDogs = [Dog objectsWithPredicate:pred];
Realm 在oc上的基礎使用就先講這些,下篇將繼續(xù)對使用個過程中出現(xiàn)的問題及優(yōu)化等作出講解。感謝您提出寶貴意見。