【问题标题】:GAE+Objectify - Parameterized type com.googlecode.objectify.Ref not supportedGAE+Objectify - 不支持参数化类型 com.googlecode.objectify.Ref
【发布时间】:2014-07-05 20:59:49
【问题描述】:

我正在使用 Google App engine1.9.3、Eclipse、Objectify5.03。我的班级如下:

import com.googlecode.objectify.Ref;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Load;

@Entity
public class User {

@Id private Long userId;
private String userName;
@Load private Ref<UserDetails> userDetails;
@Load private Ref<UserPassword> userPassword;

//getters & setters 

}

当我尝试通过 Eclipse 为此类创建 google 端点时,我收到以下错误: java.lang.IllegalArgumentException:不支持参数化类型 com.googlecode.objectify.Ref

这是我第一次尝试 Objectify。

任何想法我做错了什么。从我目前所读到的任何内容来看,GAE 端点和 Objectify 应该可以工作,对吗?

【问题讨论】:

  • 您可能应该用与 Endpoints 相关的内容来标记这个问题,因为那是可以回答您问题的社区。​​span>
  • 我猜你的User 类会有一个getter 来返回UserDetailsUserPassword 对象,而不是它们各自的Ref&lt;&gt;s?如果是这样,您可能需要查看 Endpoint annotation docs 中的 @ApiResourceProperty,因为您可能需要告诉 Cloud Endpoints 忽略您的私有 Objectify Ref&lt;&gt; 成员。

标签: eclipse google-app-engine google-cloud-endpoints objectify


【解决方案1】:

Google Cloud Endpoints 无法序列化 Ref 对象,因为它是由 objectify 定义的任意对象,因此如错误所示不受支持。

这是 Cloud Endpoints 的已知限制,因为它不允许使用自定义对象。如果您有兴趣,特别是在这一点上有一个完整的讨论线程:Cloud endpoints .api generation exception when using objectify (4.0b1) parameterized key

您必须使用@ApiResourceProperty 注释您的方法,并将其忽略的属性设置为true,如下面的代码所示:

import com.googlecode.objectify.Ref;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Load;
import com.google.api.server.spi.config.AnnotationBoolean;
import com.google.api.server.spi.config.ApiResourceProperty;

@Entity
public class User 
{
    @Id private Long userId;
    private String userName;
    @Load private Ref<UserDetails> userDetails;
    @Load private Ref<UserPassword> userPassword;

    //getters & setters
    @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) 
    public UserDetail getUserDetails(){
    }

    @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) 
    public UserPassword getUserPassword(){
    }
}

如果您仍想使用这些对象中保存的数据,请考虑在您的类中添加一些字段来保存数据并在 User 类完成加载后初始化它们,如下所示:

@Ignore String firstName;
@OnLoad
void trackUserDetails() 
{ 
    this.firstName = getUserDetails().getFirstName(); 
    // add more code here to set other fields, you get the gist
}

但在我看来,更好的方法是重新考虑课程的设计,或者重新考虑你想要做什么。

【讨论】:

  • elcid,我知道这是一个简单的实现,我可以在同一个实体中拥有所有字段,但我试图找出 Objectfy + Google 端点是否能够支持一对一和一对多的关系。例如,如果我的用户有一个帐户列表,我打算添加 List> 帐户。当我的前端从数据存储中检索用户时,用户也应该可以使用帐户列表。我们是否说这是不可能的,我需要添加一个单独的查询来获取用户的帐户。
  • 我添加了 @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) 到上面 elcid 详述的 getter 和 setter。但是,当我尝试通过 Eclipse 为用户创建云端点类时,我仍然得到'Caused by: java.lang.IllegalArgumentException: Parameterized type com.googlecode.objectify.Ref not supported'。如果有人有任何其他建议,请告诉我。
  • @DavidC 据我所知,Google Cloud Endpoints (GCE) 不知道如何序列化/反序列化由 objectify 定义的自定义 Ref 对象,因此为什么编译失败是因为它不知道如何将您的帐户列表发送给您的客户。您可以尝试将您的实际实体而不是 Ref 发送给您的客户。关于您最近的问题,请尝试使用 @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) 注释 Ref 属性。
【解决方案2】:

ApiResourceProperty 注释不适用于 Google Emdpoints+Objectify 组合,因为 Ref 或 Key 是 Objectify 特定类,Google Endpoints 无法识别它们,并且在您尝试生成客户端库时会出错。我改变了用户类如下。

 @Id private Long userId;
 @Index private String userName;
 @Load private UserDetails userDetails;
 @Load private UserPassword userPassword;
 @Load private ArrayList<Account> userAccounts;

 //getters and setters

当我按如下用户名检索用户时,我会通过 getter 获取用户、用户详细信息、用户密码以及用户帐户列表(一次性)

@ApiMethod(name = "getUserByName", path = "get_user_by_name")
public User getUserByName(@Named("userName") String userName) {

    User user = null;
    try {
         user = ofy().load().type(User.class).filter("userName", userName).first().now();
         if(user != null)
             log.info("UserEndpoint.getUserByName...user retrieved="+user.getUserId());
         else
             log.info("UserEndpoint.getUserByName...user is null");
    } catch(Exception e) {
        log.info("UserEndpoint.getUserByName...exception="+e.getMessage());
    }
    return user;
}

当我在 Google 控制台上使用 Datastore Viewer 查看数据时,我在 User 表的 userDetails、userPassword 和 Accounts 列中看到了一些条目。我假设这些是对各自表中实际数据的引用,而不是数据本身的副本。希望这会有所帮助。

【讨论】:

  • 您在这里所做的是创建一个嵌入式实体列表,而当您使用 @Ref 时,您与另一个实体有关系..这就是为什么现在您在 1 列中看到完整的对象德 DS 查看器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多