Realm 中的@LinkingObjects 注解是如何工作的
How does the @LinkingObjects annotation in Realm work
我有一个 Android 应用程序,它使用 SQLite 及其 json1 扩展作为其数据库后端。虽然这有效,但操作 JSON 所需的 SQL 很难理解,甚至更难维护。因此,我目前正在尝试使用 Realm 作为替代方案。虽然 Realm 在很大程度上是直观的,但 LinkingObjects 是一个我不完全理解的功能。考虑以下我目前使用的 classes
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 版本中,我通过引用其 AUTO_INCREMENTing id
字段来识别每个 PassPoint
使用的 GridNode
。使用 Realm,事情变得简单多了,因为我可以简单地将 GridNode 本身用作 PassPoint 的属性。
这是事情变得不太清楚的地方。假设我通过 运行 一个 RealmQuery 例如
从 Realm
中检索一个现有的 GridNode
myrealm.where(GridNode.class).equalTo("lx",23).equalTo("ly",32).findFirst();
阅读字里行间我得出的结论是 运行 宁此查询不仅会获取我之后的 GridNode,而且 运行 使用我的
的隐式查询
@LinkingObjects("gridnode")
private final RealmResults<PassPoint> passpoints = null;
用于检索引用相关 GridNode 的所有 PassPoint
对象的列表的注释。
非常方便,但我发现自己想知道这是否需要付出代价 - 运行 该查询所需的时间。假设我还有一些其他 classes 也引用 GridNodes,在这种情况下,我将有进一步的 @LinkingObjets
注释,这将导致进一步的隐式查询?
与此相反,如果我只是记录一个 GridNode id,那么我可以在需要时自己处理识别相关的 GridNode 吗?实际上,用便利换取速度和响应能力?
或者我只是简单地读错了字里行间,这根本不是 @LinkingObjects
的工作原理?
另一件不太清楚的事情 - 正如您将注意到的 gridnode
是 PassPoint
class 的私有成员。那么我如何才能在我的 GridNode
class 中创建 @LinkingObjects("gridnode")
注释,而编译器不会抱怨我试图访问一个从 PassPoint
外部不可见的成员 class?
Reading between the lines I have concluded that running this query will not only fetch the GridNode I am after but run an implicit query
没有。不完全是。
正如 Realm 文档所述here:
All fetches (including queries) are lazy in Realm, and the data is never copied.
这意味着定义查询的简单情况就是这样 - 它定义了它。但在用户明确请求之前,它不会 evaluate/execute 查询。因此,具有查询字段(例如 LinkingObjects
字段)的对象提供了一种简单的方法,用户可以通过该方法执行查询,但不会仅仅因为对象本身已加载就自动执行。只有 运行 当 findFirst
或 findAll
(或类似的)调用时。
因此,如果您从未真正访问过 GridNode.passpoints
字段,则它永远不会被执行。
您可以通过一个简单的实验向自己证明这一点:-
- 从没有链接
PassPoint
的领域中检索 GridNode
。
- 访问链接对象字段并检查它是否为空。
- 向领域添加一个新的
Passpoint
并引用相同的 GridNode
。
- 重新测试您在步骤 1 中检索到的同一对象的链接对象字段,您应该会看到查询结果现在包含新的
Passpoint
.
关于你的第二个问题,简单的回答是你的模型字段的保护级别只适用于你数据的Java模型;它不适用于底层 Realm 模型。
我有一个 Android 应用程序,它使用 SQLite 及其 json1 扩展作为其数据库后端。虽然这有效,但操作 JSON 所需的 SQL 很难理解,甚至更难维护。因此,我目前正在尝试使用 Realm 作为替代方案。虽然 Realm 在很大程度上是直观的,但 LinkingObjects 是一个我不完全理解的功能。考虑以下我目前使用的 classes
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 版本中,我通过引用其 AUTO_INCREMENTing id
字段来识别每个 PassPoint
使用的 GridNode
。使用 Realm,事情变得简单多了,因为我可以简单地将 GridNode 本身用作 PassPoint 的属性。
这是事情变得不太清楚的地方。假设我通过 运行 一个 RealmQuery 例如
从Realm
中检索一个现有的 GridNode
myrealm.where(GridNode.class).equalTo("lx",23).equalTo("ly",32).findFirst();
阅读字里行间我得出的结论是 运行 宁此查询不仅会获取我之后的 GridNode,而且 运行 使用我的
的隐式查询@LinkingObjects("gridnode")
private final RealmResults<PassPoint> passpoints = null;
用于检索引用相关 GridNode 的所有 PassPoint
对象的列表的注释。
非常方便,但我发现自己想知道这是否需要付出代价 - 运行 该查询所需的时间。假设我还有一些其他 classes 也引用 GridNodes,在这种情况下,我将有进一步的 @LinkingObjets
注释,这将导致进一步的隐式查询?
与此相反,如果我只是记录一个 GridNode id,那么我可以在需要时自己处理识别相关的 GridNode 吗?实际上,用便利换取速度和响应能力?
或者我只是简单地读错了字里行间,这根本不是 @LinkingObjects
的工作原理?
另一件不太清楚的事情 - 正如您将注意到的 gridnode
是 PassPoint
class 的私有成员。那么我如何才能在我的 GridNode
class 中创建 @LinkingObjects("gridnode")
注释,而编译器不会抱怨我试图访问一个从 PassPoint
外部不可见的成员 class?
Reading between the lines I have concluded that running this query will not only fetch the GridNode I am after but run an implicit query
没有。不完全是。
正如 Realm 文档所述here:
All fetches (including queries) are lazy in Realm, and the data is never copied.
这意味着定义查询的简单情况就是这样 - 它定义了它。但在用户明确请求之前,它不会 evaluate/execute 查询。因此,具有查询字段(例如 LinkingObjects
字段)的对象提供了一种简单的方法,用户可以通过该方法执行查询,但不会仅仅因为对象本身已加载就自动执行。只有 运行 当 findFirst
或 findAll
(或类似的)调用时。
因此,如果您从未真正访问过 GridNode.passpoints
字段,则它永远不会被执行。
您可以通过一个简单的实验向自己证明这一点:-
- 从没有链接
PassPoint
的领域中检索GridNode
。 - 访问链接对象字段并检查它是否为空。
- 向领域添加一个新的
Passpoint
并引用相同的GridNode
。 - 重新测试您在步骤 1 中检索到的同一对象的链接对象字段,您应该会看到查询结果现在包含新的
Passpoint
.
关于你的第二个问题,简单的回答是你的模型字段的保护级别只适用于你数据的Java模型;它不适用于底层 Realm 模型。