5

Ho un oggetto account che fa riferimento a un oggetto utente.Objectify carica oggetto dietro Rif. <?> anche quando @Load non è specificato

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

} 

ho nascosto le Rif come consigliato qui: http://code.google.com/p/objectify-appengine/wiki/Entities - si prega di notare il Rif fa non hanno l'annotazione @Load.

Quando chiamo Google Cloud Endpoint da un client Android, sembra che Objectify fornisca l'oggetto account con l'utente incorporato, anche se @Load non è specificato.

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

Quando interrogo l'account direttamente utilizzando le API Explorer, ho anche ottenere entrambi, account con l'utente incorporato:

200 OK 
{ 
"id": "5079604133888000", 
"user": { "id": "5723348596162560", 
"version": "1402003195251", 
"firstName": "Karl" }, 
"kind": "api#accountItem", 
"etag": "\"30khohwUBSGWr00rYOZuF9f4BTE/Q31EvnQCQ6E9c5YXKEZHNsD_mlQ\""} 

Questo solleva tre questioni:

  1. fa AppEngine restituiscono sempre i Ref incorporati in modo nativo e Objectify trasmettono sempre oggetti che già conosce?
  2. Cos'è esattamente @Load e c'è un modo per controllare questo comportamento? Carica gruppi?
  3. Ho perso qualcosa? Perché @Load non è ubbidito?

risposta

12

Nel codice esempio, non si specifica @Load il che significa che si carica l'account non verrà recuperato il User. Tuttavia, il tuo @ApiMethod sta serializzando di nuovo l'account sul client, pertanto è stata eseguita l'accesso alla proprietà user, pertanto viene emesso un recupero per caricare l'oggetto utente. Ecco perché stai ricevendo le informazioni dell'utente quando chiami il metodo.

Non specificare @Load non significa che non si otterrà uno User indietro. Significa che non recupererai uno User a meno che non lo chiedi espressamente in seguito.

Rif funziona così:

  • Sono un punto di riferimento, in modo di default non voglio recuperare i dati.
  • Se mi chiedi, allora prima caricherò i dati, poi risponderò.
  • Oh, se me lo dirai allo @Load personalmente, allora recupererò i dati inizialmente e lo preparerò per te.

Quindi questo sta lavorando bene nel codice ... ma poi la tua @ApiMethod è serializzazione l'oggetto Account al client. Il processo di serializzazione passa attraverso tutte le proprietà nell'oggetto Account, inclusa la proprietà user. A questo punto, è possibile accedere a Ref<User>, quindi i dati verranno recuperati dal Datastore e quindi restituiti al client.

Questo sta facendo il codice molto inefficiente, dal momento che i Account oggetti vengono caricati senza le informazioni User, ma poi si accede sempre informazioni User successivamente (durante la serializzazione), l'emissione di recuperare una parte.Il batch gets dal Datastore è molto più efficiente rispetto all'emissione di gets separato.

Nel tuo caso, si può fare una delle due cose:

  1. Aggiungere @Load alla proprietà utente, quindi l'oggetto Account viene recuperata in modo efficiente.
  2. Il tuo @ApiMethod restituisce un diverso oggetto Account senza la proprietà user (evitando così di recuperare l'utente se non è necessario).

L'opzione 2 di cui sopra è molto utile poiché è possibile astrarre la struttura interna del Datastore da ciò che vede il client. Ti troverai a usare questo patter abbastanza spesso.

+2

Grazie @svpino per la risposta molto dettagliata e credo che questo è ** molto importante per tutti coloro che sta usando oggettivare con il riposo **. Non mi è stato chiaro che anche se non accedo esplicitamente al codice <> dal mio codice, il serializzatore lo fa. –

+0

Cosa succede se imposto l'oggetto utente come null prima di inviarlo al client? – Dexter

Problemi correlati