2013-07-26 9 views
26

Restful zasoby nie zawsze mają odwzorowanie typu jeden-do-jednego z jednostkami jpa. Jak widzę, jest kilka problemów, które próbuję wymyślić, jak obsługiwać:Co to jest dobra strategia przekształcania podmiotów jpa w zasoby restrykcyjne

  1. Gdy zasób zawiera informacje zapełnione i zapisane przez więcej niż jeden obiekt.
  2. Gdy jednostka zawiera więcej informacji, które chcesz wysłać jako zasób. Mogę po prostu użyć Jackson'a @JsonIgnore, ale nadal będę miał numer 1, 3 i 4.
  3. Kiedy jednostka (jak zagregowany root) ma zagnieżdżone byty i chcesz dołączyć część zagnieżdżonych elementów, ale tylko do pewnego poziomu zagnieżdżanie jako zasób.
  4. Jeśli chcesz wykluczyć jeden element podmiotu, gdy jest on częścią jednej jednostki nadrzędnej, ale wyklucza oddzielny element, gdy jest częścią innej jednostki nadrzędnej.
  5. Blasted referencje okrągłe (mam to przede wszystkim praca z JSOG użyciu @JsonIdentityInfo Jacksona)

Możliwe rozwiązania: Jedynym sposobem mogę myśleć, że będzie obsługiwać wszystkie te kwestie będą tworzyć całość pęczek klas "zasobów", które miałyby konstruktorów, którzy wzięli potrzebne jednostki do zbudowania zasobu i wstawili niezbędne moduły pobierające i ustawiające dla tego zasobu. Czy to przesada?

Aby rozwiązać 2, 3, 4 i 5, mógłbym po prostu zrobić pewne przetwarzanie przed i po rzeczywistym obiekcie przed wysłaniem go do Jacksona, aby przekształcić do postaci szeregowej lub deserializować mój program do JSON, ale to nie rozwiązuje problemu 1.

Są to wszystkie problemy, które myślę, że inni by się zetknęli i jestem ciekawy, jakie rozwiązania mogą wymyślić inni ludzie. (Obecnie używam JPA 2, Spring MVC, Jackson i Spring-Data, ale jestem otwarty na inne technologie)

Odpowiedz

25

Dzięki kombinacji JAX_RS 1.1 i Jackson/GSON można bezpośrednio ujawnić podmioty WZP jako zasoby REST, ale napotkasz niezliczoną ilość problemów.

DTO, czyli prognozy dla podmiotów WZP są drogą do zrobienia. Pozwoliłoby to oddzielić obawy dotyczące reprezentacji zasobów od usług REST od kwestii transakcyjnych związanych z JPA. Możesz wyraźnie określić charakter reprezentacji. Możesz kontrolować ilość danych, które pojawiają się w reprezentacji, w tym głębokość wykresu obiektu, który ma być przesuwany, jeśli dokładnie projektujesz swoje DTO/prognozy. Może być konieczne utworzenie wielu DTO/prognoz dla tej samej jednostki JPA dla różnych zasobów, w których jednostka może być potrzebna do reprezentowania w inny sposób.

Ponadto, z mojego doświadczenia wynika, że ​​używanie adnotacji, takich jak @JsonIgnore i @JsonIdentityInfo na jednostkach JPA, nie nadaje się dokładnie do bardziej użytecznych reprezentacji zasobów. Możesz w końcu wpaść w kłopoty przy łączeniu obiektów z powrotem w kontekście utrwalania (z powodu zignorowanych właściwości), albo twoi klienci mogą nie być w stanie wykorzystać reprezentacji zasobów, ponieważ odniesienia do obiektu jako schematu mogą nie być zrozumiałe. Większość klientów JavaScript zazwyczaj ma problemy z referencjami do obiektów, które powstają w wyniku adnotacji @JsonidentityInfo, z powodu braku standaryzacji.

Istnieją inne dodatkowe aspekty, które byłyby możliwe poprzez DTO/prognozy. JPA @EmbeddedId s nie pasują do reprezentacji zasobów REST w sposób naturalny. Niektórzy adwokaci używają adnotacji JAX-RS @MatrixParam do identyfikowania zasobu w unikalny URI zasobów, ale to nie działa po wyjęciu z pudełka dla większości klientów. Parametry macierzy są przecież jedynie notatką projektową, a nie standardem (jeszcze). Za pomocą DTO/projekcji można wyświetlać reprezentację zasobów względem obliczonego identyfikatora (może to być kombinacja klawiszy składowych).

Uwaga: Obecnie pracuję nad wtyczką JBoss Forge dla REST, gdzie niektóre lub wszystkie z tych problemów istnieją i zostaną rozwiązane w przyszłych wersjach poprzez generowanie DTO.

+1

Dziękujemy za szczegółową odpowiedź. Kiedy po raz pierwszy zobaczyłem to, widziałem kilka osób, które wspomniały DTO jako możliwe rozwiązanie, ale często pojawiały się komentarze zaraz po stwierdzeniu, że nie powinieneś dodawać kolejnej warstwy. Wygląda na to, że nie stworzysz DTO dla wszystkich swoich jednostek, gdy potrzebujesz zasobu, który nie jest mapowaniem jednostki istniejącego jpa na jeden do jednego. Czy to prawda? – testing123

+1

Zgadza się. Proste modele obiektów, zwłaszcza te z relacjami jednokierunkowymi, a gdzie głębokość wykresu obiektów wynosi nie więcej niż 2, skorzystają z bezpośredniego odwzorowania między jednostkami JPA i zasobami REST. Jednak w realnym świecie nie widziałem wielu przykładów takich modeli. –

+1

Jako kontynuację, używam wzoru DTO już od jakiegoś czasu i oni byli całkowicie drogą do zrobienia. Jeszcze raz dziękuję za twoje przemyślenia :) – testing123

1

Biorąc pod uwagę twoje ograniczenia, wygląda na to, że nie ma innego rozwiązania niż obiekty przenoszenia danych - tak, zdarza się to dość często, ludzie nazwali ten wzorzec ...

10

Zgadzam się z pozostałymi odpowiedziami, że DTO są do zrobienia. Rozwiązują wiele problemów:

  1. Separacja warstw i czysty kod. Pewnego dnia może być konieczne ujawnienie modelu danych przy użyciu innego formatu (np. XML) lub interfejsu (np. Nie opartego na usługach internetowych). Utrzymywanie całej konfiguracji (takiej jak @JsonIgnore, @JsonidentityInfo) dla każdego interfejsu/formatu w modelu domenowym byłoby naprawdę kłopotliwe. DTO rozdzielają obawy. Mogą zawierać całą konfigurację wymaganą przez interfejs zewnętrzny (usługa sieciowa) bez angażowania zmian w modelu domeny, co może pozostawać niezaleŜne od formatu usługi internetowej i formatu.

  2. Bezpieczeństwo - łatwo kontrolujesz, co jest narażone na klienta i co klient może modyfikować.

  3. Wydajność - łatwo kontrolujesz, co jest wysyłane do klienta.

  4. Problemy takie jak (okrągłe) odwołania do encji, zbiory ładowane przez leniwy są również jawnie i świadomie rozwiązywane przez użytkownika podczas konwersji na DTO.

+0

Wszystkie zalety, dzięki za udostępnienie. – testing123

0

Jeśli twoja aplikacja jest kompletnie ZNAMIONA, to jest zdecydowanie Spring REST, w której absolutnie nie potrzebujesz DTO. Jeśli jest to bardziej skomplikowane, będziesz bezpieczniejszy dzięki DTO zabezpieczającym warstwę aplikacji. Ale nie próbuj enkapsulować DTO wewnątrz warstwy kontrolera. Należą one do warstwy usługi, ponieważ mapowanie jest również częścią logiki (co pozwalasz aplikacji i co z niej rezygnujesz). W ten sposób warstwa aplikacji pozostaje hermetyczna. Oczywiście w większości przypadków może to być mieszanka tych dwóch.

Powiązane problemy