Realm(Java)數據庫使用文檔(目錄)
通過繼承RealmObject
基類來創建Realm模型:
public class User extends RealmObject {
private String name;
private int age;
@Ignore
private int sessionId;
// IDE生成的標準getters和setters…
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public int getSessionId() { return sessionId; }
public void setSessionId(int sessionId) { this.sessionId = sessionId; }
}
Realm model字段支持public、protected和private修飾符以及自定義方法。
public class User extends RealmObject {
public String name;
public boolean hasLongName() {
return name.length() > 7;
}
@Override
public boolean equals(Object o) {
// Custom equals comparison
}
}
3.1 字段類型
Realm支持boolean、byte、short、int、long、float、double、String、Date
和byte[]
字段類型。數值類型byte、short、int
和long
在Realm中都映射爲long
。除了這些標準字段類型之外,Realm還支持RealmObject
和RealmList <? extends RealmObject>
擴展爲模型關係。
裝箱的Boolean、Byte、Short、Integer、Long、 Float
和Double
也可以在模型類中使用。這些類型的值可能爲null
。
3.2 必填字段
@Required
註解可用於標記Realm字段中禁止爲空值,使其成爲必填字段,而不是可選字段。 使用@Required只能註釋Boolean、Byte、Short、Integer、Long、Float、Double、String、byte[]
和Date
。 如果將其添加到其他字段類型,編譯將失敗。
具有基本類型和RealmList
類型的字段是非必需的。RealmObject
類型的字段始終可以爲空。
3.3 主鍵
使用@PrimaryKey
註解將字段標記爲model的主鍵。字段類型必須是字符串(String
)或整數(byte, short、int、long、Byte、Short、Integer
和Long
)。 使用字符串字段作爲主鍵會自動爲該字段建立索引:字符串上的@PrimaryKey
註解隱式設置了@Index
註解。Realm不支持複合鍵,即使用多個字段作爲單個主鍵。
使用主鍵可以使用copyToRealmOrUpdate()
或insertOrUpdate()
方法。它們查找具有給定主鍵的對象,然後更新它(如果具有該鍵的對象已經存在)或創建它(如果鍵不存在)。如果在沒有主鍵的類上調用copyToRealmOrUpdate()
或insertOrUpdate()
,則會引發異常。
當您使用主鍵時,讀取(查詢)會稍微快一些,但是寫入(創建和更新對象)會慢一些。 性能上的變化將取決於Realm數據集的大小。
請注意,Realm.createObject
返回一個新對象,其所有字段均設置爲其默認值。 如果對象是具有主鍵的類,則可能會產生衝突(可能已經存在具有該主鍵集的對象)。 爲避免這種情況,您可以創建一個非託管對象,設置其字段值,然後使用copyToRealm()
或insert()
將其添加到Realm:
final MyObject obj = new MyObject();
obj.setId(42);
obj.setName("Fish");
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
// 在Realm中創建一個新對象,或者如果該對象已經存在(相同的主鍵),則拋出異常。
// 更新具有相同主鍵的現有對象,或者如果沒有主鍵的對象= 42,則創建一個新對象
realm.copyToRealmOrUpdate(obj);
}
});
除非@PrimaryKey
與@Required
註解結合使用,否則String
類型或裝箱的整數(Byte,Short,Integer
和Long
)的主鍵可以具有null
值。
3.4 索引屬性
要爲字段建立索引,請像主鍵一樣使用@Index
註解。這會使寫入速度稍慢,但會使讀取速度更快。(存儲索引也會使您的Realm文件略大)最好僅在針對特定情況優化讀取性能時才添加索引。
可以String、byte、short、int、long、boolean
和Date
字段使用索引。
3.5 忽略屬性
如果您不想將model中的字段保存到Realm,請使用註解@Ignore
。例如,如果您的輸入包含比model更多的字段,並且您不想有很多特殊情況來處理這些未使用的數據字段,則可以這樣做。
標記爲static
和transient
的字段始終被忽略,並且不需要@Ignore
註解。
3.6 計數器Counters
Realm提供MutableRealmInteger
作爲特殊的整數類型。 MutableRealmInteger公開了一個附加API,可以在使用同步Realms
時更清楚地表達意圖並生成更好的衝突解決步驟。
傳統上,將通過讀取一個值,對其進行遞增並設置它來實現計數器(myObj.counter + = 1
)。 在異步情況下(例如,當兩個客戶端脫機時),不能好好工作,因爲雙方將讀取一個值,例如10,對其進行遞增,然後將該值存儲爲11。最終,當他們重新獲得連接並嘗試合併其值時 更改後,他們將同意計數器位於11而不是預期的12。
MutableRealmIntegers
由傳統的整數類型支持,因此將字段從byte、short、int
或long
更改爲MutableRealmInteger
時不需要遷移。
MutableRealmInteger
不是像Java中的原始數字類型那樣的不可變類型標準。 它是一個實時對象,例如RealmObject,RealmResults
和RealmList
。這意味着寫入Realm時,MutableRealmInteger
內部包含的值可以更改。 因此,必須將MutableRealmInteger
字段標記爲final
。
public class Party extends RealmObject {
public final MutableRealmInteger guests = MutableRealmInteger.valueOf(0);
}
要更改計數器值,只需調用counter.increment()
或counter.decrement()
。
Party party = realm.where(Party.class).findFirst();
realm.beginTransaction();
party.guests.get(); // 0
party.guests.increment(1); // 1
party.guests.decrement(1); // 0
party.guests.increment(5); // 5
party.guests.decrement(1); // 4
realm.commitTransaction();
要重置計數器,可以使用counter.set()
爲它分配一個新值。
調用set()可能會覆蓋來自其他設備increment()和decrement()操作。正常的最後合併寫入成功,因此僅在有損計數器可接受的情況下才應進行這些操作的混合。
Party party = realm.where(Party.class).findFirst();
realm.beginTransaction();
party.guests.set(0);
realm.commitTransaction();
3.7 覆蓋屬性名稱
默認行爲是Realm將使用model類中定義的名稱作爲名稱來表示Realm文件內部的類和字段。 在某些情況下,您可能想要更改此行爲:
- 支持具有同一項目但位於不序包中的兩個model類。
- 爲了簡化跨平臺架構的使用,因爲命名約定不同。
- 要使用比Realm強制使用的57個字符的限制長的Java類名。
- 在Java中更改字段名稱而不會強制應用程序用戶完成遷移過程。
在這些情況下,可以使用@RealmModule,@RealmClass
或@RealmField
註解定義其他名稱,以覆蓋內部使用的名稱。
您可以在module定義命名策略,這將影響module的所有類部分:
@RealmModule(
allClasses = true,
classNamingPolicy = RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES,
fieldNamingPolicy = RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES
)
public class MyModule {
}
您可以爲該類定義自定義名稱,或者可以定義將影響該類中所有字段的字段命名策略。 這將覆蓋所有module級別的設置:
@RealmClass(name = "__Person", fieldNamingPolicy = RealmNamingPolicy.PASCAL_CASE)
public class Person extends RealmObject {
public String name;
}
您可以爲字段定義自定義名稱,這將覆蓋所有Class類和Module模塊級別的設置:
public class extends RealmObject {
@RealmField(name = "person_name")
public String name;
}
選擇與Java模型類中使用的名稱不同的內部名稱具有以下含義:
- DynamicRealm上的查詢必須使用內部名稱。 普通Realm實例上的查詢必須繼續使用Java類中定義的名稱。
- 創建類和字段時,遷移必須使用內部名稱。
- 報告的架構錯誤將使用內部名稱。
請注意,更改內部名稱不會影響從JSON導入數據。 JSON數據仍必須遵循Realm Java類中定義的名稱。
在使用Moshi,GSON或Jackson之類的標準庫解析JSON時,請務必記住這些庫定義了從JSON到Java的轉換,同時設置了內部Realm名稱也定義了從Java到Realm文件的轉換。這意味着如果您想使用這些庫將數據從JSON導入Realm,則仍然需要提供JSON解析器庫和Realm的註釋。
使用Moshi,它看起來像這樣:
public class Person extends RealmObject {
@Json(name = "first_name") // JSON輸入中使用的名稱。
@RealmField(name = "first_name") // Realm文件內部使用的名稱。
public string firstName; // Java中使用的名稱
}
有關更多信息,請參見RealmNamingPolicy。