即使未指定@Load,Objectify也会在Ref <?>后面加载对象

Oli*_*ler 5 java google-app-engine objectify google-cloud-endpoints

我有一个引用用户对象的帐户对象.

@Cache
@Entity
public final class Account {

    @Id Long id;
    @Index private Ref<User> user;

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }

    public User getUser() {
        return user.get();
    }
    public void setUser(User user) {
        this.user = Ref.create(user);
    }

}
Run Code Online (Sandbox Code Playgroud)

我按照此处的建议隐藏了参考资料:http://code.google.com/p/objectify-appengine/wiki/Entities - 请注意参考资料没有 @Load注释.

当我从Android客户端调用我的Google Cloud Endpoint时,看起来Objectify会向嵌入式用户提供帐户对象,即使未指定@Load也是如此.

@ApiMethod(name = "account.get")
public Account getAccount(
        @Named("id") final Long id
) {
    return ofy().load().type(Account.class).id(id).now();
}
Run Code Online (Sandbox Code Playgroud)

当我使用Apis Explorer直接查询帐户时,我同时获得了嵌入用户的帐户:

200 OK
{ 
"id": "5079604133888000", 
"user": {  "id": "5723348596162560",  
"version": "1402003195251",  
"firstName": "Karl" }, 
"kind": "api#accountItem", 
"etag": "\"30khohwUBSGWr00rYOZuF9f4BTE/Q31EvnQCQ6E9c5YXKEZHNsD_mlQ\""}
Run Code Online (Sandbox Code Playgroud)

这提出了三个问题:

  1. Appengine是否总是原生地返回嵌入的Refs并且Objectify总是传递它已经知道的对象吗?
  2. @Load究竟是什么,有没有办法控制这种行为?加载组?
  3. 我错过了什么吗?@Load为什么不服从?

svp*_*ino 13

在您的示例代码中,您没有指定@Load哪个加载帐户不会获取User.但是,您@ApiMethod正在将帐户序列化回客户端,因此user已访问该属性,因此会发出单独的提取以加载用户对象.这就是您在调用方法时获取用户信息的原因.

没有具体说明@Load并不意味着你不会User退缩.这意味着User除非您稍后特别要求,否则您不会检索它.

Ref的工作原理如下:

  • 我是一个参考,所以默认情况下我不会获取数据.
  • 如果您要求我,那么我将首先加载数据,然后回答您.
  • 哦,如果你告诉我@Load自己,那么我将最初获取数据并为你做好准备.

所以这在你的代码中工作得很好......但是你@ApiMethod正在将你的Account对象序列化回客户端.序列化过程将遍历Account对象中的每个属性,包括user属性.此时,Ref<User>正在访问,因此数据将从数据存储区中获取,然后返回到客户端.

这使得您的代码效率非常低,因为在Account没有User信息的情况下加载对象,但随后您总是在User稍后(在序列化期间)访问信息,发出单独的提取.gets从数据存储区进行批处理比发布单独处理方式更有效gets.

在您的情况下,您可以执行以下两种操作之一:

  1. 添加@Load到用户属性,以便Account有效地获取对象.
  2. 使您的@ApiMethod返回成为Account不具有user属性的不同对象(从而避免在不需要时获取用户).

上面的选项2非常有用,因为您可以从客户端看到的内容中抽象出内部数据存储区结构.你会发现自己经常使用这种模式.

  • 感谢@svpino提供非常详细的答案,我相信这对于使用REST**客观化的每个人来说都非常重要.我不清楚,即使我没有从代码中明确访问Ref <>,序列化程序也会这样做. (2认同)