2014-04-14 5 views
12

Ho un set di dati Spring standard JPA e Spring data Rest che, correttamente, restituisce associazioni come collegamenti alle risorse corrette.Espansione selettiva delle associazioni in Spring Data Risposta del ripetitore

{ 
    "id": 1, 
    "version": 2, 
    "date": "2011-11-22", 
    "description": "XPTO", 
    "_links": { 
     "self": { 
      "href": "http://localhost:8000/api/domain/1" 
     }, 
     "otherDomain": { 
      "href": "http://localhost:8000/api/domain/1/otherDomain" 
     } 
    } 
} 

Tuttavia, in alcuni richieste Vorrei avere l'associazione al "otherDomain" espanso (in modo che il cliente non ha a che fare N + 1 richieste per ottenere i dati completi).

È possibile configurare Spring Data Rest per gestire la risposta in questo modo?

+0

possibile duplicato di [spring-data-rest, puoi fornire tutti i dettagli dell'entità anziché (o con) link] (http://stackoverflow.com/questions/21975618/spring-data-rest-can-you -provide-full-details-of-entity-instead-of-or-with-li) – bluish

risposta

21

Le risposte predefinite dovranno rimanere invariate per garantire che i carichi utili per le richieste PUT siano simmetrici rispetto al ritorno di GET s. Tuttavia, Primavera dati REST introduce una funzionalità denominata proiezioni (si veda il JIRA ticket per i dettagli), che funziona come segue:

Si crea un'interfaccia dedicata e aggiungere tutte le proprietà che si desidera includere nella risposta:

public interface MyProjection { 

    String getMyProperty(); 

    MyRelatedObject getOtherDomain(); 
} 

è possibile

  • annotare l'interfaccia usando @Projection e posizionarlo nella stessa pacchetto come il tipo di dominio o un subpackage di esso
  • oppure registrare manualmente la proiezione utilizzando RepositoryRestConfiguration e chiamare manualmente projectionConfiguration().addProjection(…) (estendendo RepositoryRestMvcConfiguration e ignorando configureRepositoryRestConfiguration(…)).

questo farà sì che le risorse a vista per il tipo di dominio ad accettare un projection parametro (nome anche configurabile ProjectionConfiguration) con il nome della proiezione. Se specificato, ignoreremo il rendering predefinito (che include il rendering dei collegamenti alle entità correlate invece di incorporarli) e lasciare che Jackson esegua il rendering di un proxy che supporta l'interfaccia specificata.

Un esempio può essere trovato anche nel progetto Spring RESTBucks. Vedere lo OrderProjection per la definizione dell'interfaccia.

+4

È possibile espandere ulteriormente la gerarchia attraverso le proiezioni? Ad esempio se l'oggetto dietro 'otherDomain' stesso ha un'associazione a' oneMoreDomain', potrebbe anche essere aggiunto alla risposta originale? – muenchdo

+1

Penso che se il metodo 'getOtherDomain()' di 'MyProjection' restituisce una proiezione a' oneMoreDomain', allora è possibile. – djxak

+1

@Oliver Gierke, MI HAI SALVATO ALCUNI BACON! Questo dovrebbe essere davvero nei documenti ufficiali, mi chiedo perché non lo è :(http://docs.spring.io/spring-data/rest/docs/2.2.1.RELEASE/reference/html/ In realtà voglio espandermi alcune associazioni 'EAGER' per la proiezione predefinita, ma non riesco a farlo :(Sai come? Quindi per ora,' @ Projection' funziona ... Archiviato https://jira.spring.io/browse/DATAREST-419 –

0

La mia soluzione si applica a tutte le richieste, ma alcune potrebbero trovare pertinente.

Ho una situazione simular, dove ho le userPersons associazione annidato nel mio utente risposta JSON, in questo modo:

{ 
"_embedded":{ 
    "users":[ 
    { 
     "userName":"Albert" 
     "userPersons":[ 
      { 
       "personId":2356, 
       "activeBoolean":1 
      }, 
      { 
       "personId":123617783, 
       "activeBoolean":1 
      } 
     ], 
     "_links":{ 
      "self":{ 
       "href":"http://localhost:8080/api/users/1" 
      } 
     } 
    } 
    ] 

} }

mia entità di base in questo modo:

@Entity 
public class User { 


... 

@Getter @Setter 
private String userName; 

@Getter @Setter 
@OneToMany(mappedBy = "user") 
private Set<Userperson> userPersons; 

}

E un unico repository:

@RepositoryRestResource 
public interface UserRepo extends JpaRepository<User, Integer> { 
} 

La mia soluzione è questa:

Semplicemente NON esponendo un Userperson @RepositoryRestResource, Primavera dati Resto incorporerà la vostra associazione.

Se si definisce @RepositoryRestResource per il tipo annidato, Spring Data Rest renderà un collegamento alla risorsa e non lo incorpora.

Se è necessario il repository di tipo nidificato per la business logic interna, impostarlo su @RepositoryRestResource (exported = false), per avere lo stesso comportamento.

Per evitare il problema 1 + N, è possibile configurare l'associazione per il caricamento ansioso, magari utilizzando un @EntityGraph come this guy - sebbene non abbia ancora trovato il modo migliore per implementarlo in Spring Data Rest.