2016-06-29 11 views
8

Używam Spring Data REST i Hateoas w połączeniu z przeglądarką HAL. Działa to doskonale, ale teraz chciałbym wykonać zrzut JSON konkretnej jednostki z (zestawem) powiązanych obiektów. Użyłem @Projection, ale potem utknąłem ponownie.Spring Data REST Jak dodać wbudowane zasoby inline

FYI: Normalne zachowanie (z osadzonymi i linkami itp.) Powinno pozostać poza nowym punktem końcowym (bez osadzonych i linków).

Aby dodatkowo zilustrować mój problem/pytanie:

class Person { 
    String name; 
    List<Company> companies; 
} 

class Company { 
    String name; 
    Address address; 
} 

class Address { 
    String street; 
} 

teraz chciałbym zobaczyć coś takiego:

{ 
    "name": "John", 
    "companies": [ 
     { 
      "name": "Stackoverflow", 
      "address": {"street": "Highway blvd."} 
     }, 
     { 
      "name": "Oracle", 
      "address": {"street": "Main rd."} 
     } 
    ] 
} 

Choć dostaję to:

{ 
    "name": "John", 
    "_links": { 
     "self": {"href": "http...."}, 
     "companies": {"href": "http ..."} 
    }, 
} 

Zobacz także: http://docs.spring.io/spring-data/rest/docs/current/reference/html/#projections-excerpts

W moim przykładzie przedstawiłem dwie trudności, które mam: Listy (firmy) i wiele poziomów: osoba-> firma-> adres. Oba są wymagane do pracy (prawdopodobnie 5 poziomów, z których niektóre mają "wiele" relacji).

+0

można przez nie przy użyciu Wiosna danych spoczynku.Spring Data Rest przyjmuje opinię poglądową na temat prawidłowego odpoczynku, włączając w to linki do relacji zamiast do pełnego podmiotu. –

+0

Dziękuję Deinum. Spring Data Rest znajduje się w ścieżce klas i musi tam pozostać. Czy komentarz jest nadal aktualny? – codesmith

Odpowiedz

0

W drugim punkcie końcowym, jeśli nie chcesz linki, trzeba mieć kontroler i zasobów, gdzie można mapować dane do zasobu i powrócić gromadzenie zasobów z kontrolera

+0

Dziękuję Fahad, ale czy możesz zilustrować co masz na myśli? Masz na myśli '@ Controller' i' @ Resource' lub więcej w ogóle? Jak działa to odwzorowanie danych w Twoim widoku? – codesmith

+0

Według zasobu mam na myśli klasę podobną do encji z potrzebnymi informacjami. Możesz spychacz fasoli spychacza mapować dane do zasobu. –

+0

Może to być problematyczne, gdy relacje wskazują również w drugą stronę (od adresu do firmy i od firmy do osoby, a podejście oparte na braku danych źródłowych pokaże wszystko (nieskończona pętla rekursywna). "@ JsonIgnore" nie jest opcją w tym przypadku, ponieważ wtedy widok hatoas renderuje się niepoprawnie, jeszcze tego nie testowałem, ale wydaje mi się to logiczne. – codesmith

10

przyjętym Metoda inlineing podmiotów to prognozy, które zidentyfikowałeś. Występy są zawsze wstawiane, więc jedna opcja jest stworzenie prognozy dla każdego z podmiotów, i połączyć je tak:

@Projection(name = "personProjection", types = Person.class) 
public interface PersonProjection { 

    String getFirstName(); 
    List<CompanyProjection> getCompanies(); 

} 

@Projection(name = "companyProjection", types = Company.class) 
public interface CompanyProjection { 

    String getName(); 
    AddressProjection getAddress(); 

} 

@Projection(name = "addressProjection", types = Address.class) 
public interface AddressProjection { 

    String getStreet(); 

} 

GET people/1?projection=personProjection będzie nadal świadczył _links elementy, ale dostaniesz gniazdowania chcesz:

{ 
    "companies" : [ { 
    "address" : { 
     "street" : "123 Fake st", 
     "_links" : { 
     "self" : { 
      "href" : "http://localhost:8080/addresses/1{?projection}", 
      "templated" : true 
     } 
     } 
    }, 
    "name" : "ACME inc.", 
    "_links" : { 
     "self" : { 
     "href" : "http://localhost:8080/companies/1{?projection}", 
     "templated" : true 
     }, 
     "address" : { 
     "href" : "http://localhost:8080/companies/1/address" 
     } 
    } 
    } ], 
    "firstName" : "Will", 
    "_links" : { 
    "self" : { 
     "href" : "http://localhost:8080/people/1" 
    }, 
    "person" : { 
     "href" : "http://localhost:8080/people/1{?projection}", 
     "templated" : true 
    }, 
    "companies" : { 
     "href" : "http://localhost:8080/people/1/companies" 
    } 
    } 
} 

Ewentualnie, jeśli nie trzeba narażać Company i Address podmioty jako zasobów odpoczynku, można oznaczyć swoje repozytoria z @RepositoryRestResource(exported=false) i będą wstawiane gdziekolwiek one są odniesione, bez potrzeby projekcji.

Jednak ostateczne zastrzeżenie - ta prośba nieco walczy z etosem Spring REST i Spring HATEOAS oraz zaprasza duże, nieporęczne zapytania z problemem n + 1. Pamiętaj, że Spring Data REST nie jest rozwiązaniem "pod klucz" do przekształcania modelu domeny w API, a renderowanie głębokich wykresów obiektów (jeśli jest to twoim zamiarem) jest potencjalnie czymś, co możesz odsłonić jako punkt kontrolny niestandardowego kontrolera na zasadzie ad-hoc, gdzie może dokładnie kontrolować warunki.

-1

Uważam, że najlepszym sposobem, aby osadzić listy lub HashMap jest poprzez przekształcenie go w ciąg json i powrót do obiektu java kiedy czytasz ....

można to łatwo zrobić za pomocą

@Convert(converter = PluginAnalyzerConfigConverter.class) 
    private PluginAnalyzerConfig configuration; 
//in Entity Class 

// declare a converter class like this 
public class PluginAnalyzerConfigConverter implements 
    AttributeConverter<PluginAnalyzerConfig, String> { 

    @Override public String convertToDatabaseColumn(PluginAnalyzerConfig config) { 
    Gson parser = new Gson(); 
    return parser.toJson(config, PluginAnalyzerConfig.class); 
    } 

    @Override public PluginAnalyzerConfig convertToEntityAttribute(String source) { 
    Gson parser = new Gson(); 
    return parser.fromJson(source, PluginAnalyzerConfig.class); 
    } 
} 

jak pokazano na Spring Data with Mysql JSON type

Mamy coś podobnego w Spring danych DynamoDb - dla AWS DynamoDB

Powiązane problemy