2014-06-08 67 views
1

這裏和網絡上有很多文章,但這些文章都針對不同的Objectify版本,並且似乎不適用於其中一個原因。Objectify後端和客戶端之間的往返傳輸[無GWT]

我有一個實體,它引用了另一個實體(例如帳戶實體引用用戶實體):

@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); 
    } 

} 

我試圖做到這一點:

  1. 從客戶端,獲取通過REST/Google Cloud Endpoints帳戶實體。
  2. 修改資源。
  3. 在服務器上更新它。

正如這裏所討論的Objectify loads object behind Ref<?> even when @Load is not specified上面的代碼總是返回引用的用戶,以及我不想要的。

正如@svpino所建議的那樣,「使您的@ApiMethod返回一個不帶用戶屬性的不同Account對象(從而避免在不需要的情況下提取用戶)」。只要我不想更新資源,這就可以工作。如果我需要更新,鑰匙/參考需要保留(即使我不需要客戶端)。

我可以看到的一種可能的方法是使用Key而不是Ref並呈現Web安全字符串,然後在UPDATE期間重新創建用戶。

private Key<User> user; 

public String getUser() { 
    return user.toString(); 
} 
public void setUser(String user) { 
    this.user = Key.create(user); 
} 

的字符串看起來像「密鑰(用戶(5723348596162560))」,但它似乎並沒有被重組(至少我得到一個異常這裏,還沒有跟蹤它尚未)。

另一種方法是編寫一個@ApiTransformer,它也沒有解決問題。

Jeff @StickFigure在過去幾年中發佈了好幾次,這個問題似乎還沒有解決。

Objectify 5.0.2的當前狀態是什麼?當客戶端不需要密鑰時,在往返間保留密鑰的建議是什麼?

+0

「物化負載體REF 後面即使'@不指定Load'是」不正確。當您調用Ref.get()時,Objectify將對象加載到Ref的後面。你問它,你明白了,就這麼簡單。 '@ Load'可以讓你優化加載操作。 – stickfigure

+0

如果您想在Ref 附近做更巧妙的事情,您可以在返回值之前檢查Ref.isLoaded()狀態。但請記住,這會檢查會話的狀態,因此如果該值已在請求的較早部分加載,它將返回true。 – stickfigure

回答

0

以下代碼將實體對象序列化爲網絡安全字符串,以便它可以通過REST進行傳輸。當實體被髮送回服務器時,重新構造Ref <>。通過這種方式,服務器端引用不會在對象執行往返於客戶端的過程中丟失。這種引用的對象不會傳輸到客戶端,而是可以在客戶端上「工作」爲Ref <>。

@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); 
} 

我希望這解決了問題給大家。這還沒有經過徹底的測試,所以仍然歡迎評論。

我已經運行一個測試用鑰匙<之間比較>和參考<>對我看起來甚至與參考<>時loadEntity()方法/。得到()被調用實體僅復原。因此參考<>如果@Load註釋可能更好,那麼可能會更好。也許物化人可以證實這一點。

+0

傑克遜如何知道他需要使用這些方法?我問這是因爲(而沒有)我得到:JsonMappingException:找不到類MyEntity的序列化程序,沒有發現創建BeanSerializer的屬性(以避免異常,禁用SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) –

0

你需要註釋要與@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)

谷歌文檔省略屬性說,下面講@ApiResourceProperty:

@ApiResourceProperty提供了提供了 性質如何暴露的資源更多的控制在API中。您可以在屬性獲取者 或setter上使用它來從API資源中省略屬性。如果該字段是專用字段,您也可以在字段本身使用 ,以在 API中公開它。您還可以使用此批註在API資源中更改屬性 的名稱。

我建議您訪問你的情況你的班級應該是這樣的修改之後此鏈接 https://developers.google.com/appengine/docs/java/endpoints/annotations#apiresourceproperty

那麼多看書。

​​
+0

感謝您的詳細回覆。我已經嘗試過(在字段上),但它導致Ref <>沒有被序列化。這意味着UPDATE(編號3)不能再被執行。我沒有嘗試過會發生什麼。也許它保持完好。我會嘗試在這裏發佈結果。 –

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 
}