Realm(Java)数据库使用文档(Models)


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、Datebyte[]字段类型。数值类型byte、short、intlong在Realm中都映射为long。除了这些标准字段类型之外,Realm还支持RealmObjectRealmList <? extends RealmObject>扩展为模型关系。

装箱的Boolean、Byte、Short、Integer、Long、 FloatDouble也可以在模型类中使用。这些类型的值可能为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、IntegerLong)。 使用字符串字段作为主键会自动为该字段建立索引:字符串上的@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,IntegerLong)的主键可以具有null值。

3.4 索引属性

要为字段建立索引,请像主键一样使用@Index注解。这会使写入速度稍慢,但会使读取速度更快。(存储索引也会使您的Realm文件略大)最好仅在针对特定情况优化读取性能时才添加索引。

可以String、byte、short、int、long、booleanDate字段使用索引。

3.5 忽略属性

如果您不想将model中的字段保存到Realm,请使用注解@Ignore。例如,如果您的输入包含比model更多的字段,并且您不想有很多特殊情况来处理这些未使用的数据字段,则可以这样做。

标记为statictransient的字段始终被忽略,并且不需要@Ignore注解。

3.6 计数器Counters

Realm提供MutableRealmInteger作为特殊的整数类型。 MutableRealmInteger公开了一个附加API,可以在使用同步Realms时更清楚地表达意图并生成更好的冲突解决步骤。

传统上,将通过读取一个值,对其进行递增并设置它来实现计数器(myObj.counter + = 1)。 在异步情况下(例如,当两个客户端脱机时),不能好好工作,因为双方将读取一个值,例如10,对其进行递增,然后将该值存储为11。最终,当他们重新获得连接并尝试合并其值时 更改后,他们将同意计数器位于11而不是预期的12。

MutableRealmIntegers由传统的整数类型支持,因此将字段从byte、short、intlong更改为MutableRealmInteger时不需要迁移。

MutableRealmInteger不是像Java中的原始数字类型那样的不可变类型标准。 它是一个实时对象,例如RealmObject,RealmResultsRealmList。这意味着写入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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章