这里和整个网络上有很多文章,但这些文章都针对不同的Objectify版本,似乎不是出于其中一个原因。
我有一个实体,它引用另一个实体(例如,一个帐户实体引用一个用户实体):
@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);
}
}
我正在尝试这样做:
如上所述Objectify loads object behind Ref<?> even when @Load is not specified代码总是返回引用的用户,我不想要。
正如@svpino建议的那样,一个选项是“让你的@ApiMethod返回一个不同的Account对象而没有用户属性(因此如果你不需要它,就会避免提取用户)。”只要我不想更新资源,这就可以工作。如果我需要更新,则需要保留Key / Ref(即使我在客户端上不需要它)。
我可以看到的一种可能方法是使用Key而不是Ref并呈现一个Web安全字符串,然后在UPDATE期间重新创建用户。
private Key<User> user;
public String getUser() {
return user.toString();
}
public void setUser(String user) {
this.user = Key.create(user);
}
字符串看起来像“Key(User(5723348596162560))”,但似乎没有重构(至少我在这里得到一个例外,还没有追踪它)。
另一种方法是编写一个@ApiTransformer,它也没有解决问题。
杰夫@StickFigure在过去几年中多次发布,问题似乎仍未解决。
Objectify 5.0.2的当前状态是什么?当客户端不需要密钥时,在往返之间保留密钥的建议是什么?
答案 0 :(得分:0)
您需要使用@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
Google文档说明了@ApiResourceProperty的以下内容:
@ApiResourceProperty提供了更多的资源控制 属性在API中公开。您可以在属性获取器上使用它 或者setter从API资源中省略该属性。你也可以使用 它在场上本身,如果该场是私人的,则在场上暴露它 API。您还可以使用此批注更改属性的名称 在API资源中。
我建议您访问此链接阅读更多内容 https://developers.google.com/appengine/docs/java/endpoints/annotations#apiresourceproperty
因此,在您的情况下,您的类在修改后应该如下所示。
@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;
}
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
public User getUser() {
return user.get();
}
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
public void setUser(User user) {
this.user = Ref.create(user);
}
}
答案 1 :(得分:0)
以下代码将实体对象序列化为Web安全字符串,以便可以通过REST传输。当实体被发送回服务器时,Ref&lt;&gt;重组。这样,当对象到客户端进行往返时,服务器端引用不会丢失。这种方式引用的对象不会传输到客户端并返回,但可以&#34;工作&#34;作为Ref&lt;&gt;在客户端。
@Index private Ref<User> user;
// for serialization
public String getUser() {
return user.getKey().getString(); // .toWebSafeString() will be added in future version of objectify and .toWebSafeString() will do the same as .getString()
}
public void setUser(String webSafeString) {
Key<User> key = Key.create(webSafeString);
this.user = Ref.create(key);
}
有两个单独的函数(我不承认,我承认)用于在服务器上加载实际对象以及首先创建引用:
// for load and create reference
public User loadUser() {
return user.get();
}
public void referenceUser(User user) {
this.user = Ref.create(user);
}
我希望这能为每个人解决问题。这还没有经过彻底的测试,所以仍然欢迎评论。
我已经运行了一项测试来比较使用Key&lt;&gt;和参考&lt;&gt;对我而言,即使使用Ref&lt;&gt;只有在调用loadEntity()/。get()时才重构实体。所以Ref&lt;&gt;如果可能更好,因为@Load注释将起作用。也许客观化的人可以证实这一点。
答案 2 :(得分:0)
您可以创建一个扩展Ref<User>
的类,并使用@ApiTransformer
在后端和客户端之间传输该类
@ApiTransformer(UserRefTransformer.class)
public class UserRef extends LiveRef<User>
{
}
public class UserRefTransformer implements Transformer<UserRef, User>
{
// Your transformation code goes here
}