我有一个Android应用程序,它使用SQLite及其json1扩展名作为其数据库后端。虽然这行得通,但操作JSON所需的SQL很难理解,甚至难以维护。因此,我目前正在尝试使用Realm作为替代方案。虽然Realm在大多数情况下是直观的,但LinkingObjects是我不完全了解的功能。考虑我当前使用的以下类

public class GridNode extends RealmObject
{
 @PrimaryKey
 private int id = 0;
 @Index
 private int lx = 0;
 @Index
 private int ly = 0;

 @LinkingObjects("gridnode")
 private final RealmResults<PassPoint> passpoints = null;

 //getters, setters & constructors
}


public class PassPoint extends RealmObject
{
 private GridNode gridnode;//each passpoint refers to one distinct GridNode object
 private int hits;
 private int lastVisited;

 //getters, setters & constructors
}


在当前数据的SQLite版本中,我通过引用每个GridNode的AUTO_INCREMENTing PassPoint字段来标识每个id所使用的GridNode。使用Realm,事情变得更加简单,因为我可以简单地将GridNode本身用作PassPoint的属性。

这是事情变得不太清楚的地方。假设我通过运行RealmQuery从Realm检索现有的PassPoint

myrealm.where(GridNode.class).equalTo("lx",23).equalTo("ly",32).findFirst();


仔细阅读这两行内容,我得出的结论是,运行此查询不仅会获取我所需要的GridNode,而且还会使用

@LinkingObjects("gridnode")
private final RealmResults<PassPoint> passpoints = null;


批注以检索引用所涉及GridNode的所有@LinkingObjets对象的列表。

非常方便,但我发现自己想知道这是否有代价-运行该查询所需的时间。并假设我还有一些其他类也引用GridNodes,在这种情况下,我将具有进一步的@LinkingObjects批注,这将导致进一步的隐式查询?

与此相反,如果我只记录一个GridNode id,那么我可以在需要时亲自识别相关的GridNode?实际上是为了速度和响应能力而交易便利吗?

或者,也许我只是在两行之间读错了,这根本不是gridnode的工作原理吗?

另一件事还不太清楚-您将注意到PassPoint@LinkingObjects("gridnode")类的私有成员。然后,如何在我的GridNode类中创建PassPoint批注,而编译器不会抱怨我试图访问从类外部看不到的成员?

我非常感谢您的帮助和指点。

最佳答案

仔细阅读这两行内容,我得出的结论是,运行此查询不仅将获取我所追求的GridNode,还将运行隐式查询


不,不是。

如Realm文档所述here


  所有提取(包括查询)在Realm中都是惰性的,并且永远不会复制数据。


这意味着定义查询的简单情况就是做到这一点-它定义了查询。但是它不会评估/执行查询,除非用户明确要求。因此,具有查询字段的对象(例如LinkingObjects字段)提供了一种简单的方法,用户可以通过该方法执行查询,但不能仅由于加载了对象本身而自动执行查询。仅在调用findFirstfindAll(或类似方法)时运行。

因此,如果您从未真正访问GridNode.passpoints字段,则永远不会执行它。

您可以通过一个简单的实验向自己证明这一点:


从领域中检索没有链接的GridNodePassPoint
访问链接对象字段,并检查其是否为空。
将对同一个Passpoint的引用添加到域中新的GridNode
重新测试您在步骤1中检索到的同一对象的链接对象字段,您应该看到查询结果现在包括新的Passpoint


关于第二个问题,简单的答案是,模型字段的保护级别仅适用于数据的Java模型。它不适用于基础领域模型。

10-06 05:46