我有一个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
字段)提供了一种简单的方法,用户可以通过该方法执行查询,但不能仅由于加载了对象本身而自动执行查询。仅在调用findFirst
或findAll
(或类似方法)时运行。
因此,如果您从未真正访问GridNode.passpoints
字段,则永远不会执行它。
您可以通过一个简单的实验向自己证明这一点:
从领域中检索没有链接的GridNode
的PassPoint
。
访问链接对象字段,并检查其是否为空。
将对同一个Passpoint
的引用添加到域中新的GridNode
。
重新测试您在步骤1中检索到的同一对象的链接对象字段,您应该看到查询结果现在包括新的Passpoint
。
关于第二个问题,简单的答案是,模型字段的保护级别仅适用于数据的Java模型。它不适用于基础领域模型。