Konwersja Entity na wiele DTO

Konwersja Entity na wiele DTO
EL
  • Rejestracja:około 13 lat
  • Ostatnio:3 miesiące
0

Cześć.
Mam projekt w którym zapisuje Userów do bazy, W RESTowym API przyjmuje np. UserDTO, przepuszczam to potem w serwisie przez UserConverter i na wyjściu otrzymując Entity zapisuje to do bazy. Żeby obsłużyć zapytanie o rejestrację użytkownika potrzebuje więc klasę DTO, Entity i konwerter który zamienia w obie strony.
Teraz powiedzmy że chciałbym pobrać użytkownika (np. żeby wyświetlić stronę z ustawieniami użytkownika). Część pól z poprzedniego UserDTO nie jest mi już potrzebna więc jedyne co zauwazam to dodanie kolejnego DTO i następny konwerter.
Ma to w ogóle sens? Za chwile okaże się że mam wiele DTOsów i konwerterów które niewiele się od siebie różnią. Druga sprawa że modyfikując Entity może się okazać że wszystkie te konwertery będę musiał aktualizować...
Jakiś pomysł jak coś takiego sensownie obsługiwać?
Ps. Projekt pisany w Javie ale problem jest raczej ogólny więc język nie ma tu chyba większego znaczenia.

Pozdrawiam

edytowany 1x, ostatnio: eL
Bambo
  • Rejestracja:ponad 10 lat
  • Ostatnio:7 miesięcy
  • Postów:779
0

Ja dla każdego widoku na froncie mam osobnego dtosa, ale nie muszę już nic mapować z encji - jeśli muszę coś popchać po prostu do klienta, nie updatuje mi to stanu aplikacji to wyciągam z bazy dtosa bezpośrednio przez jakiś query service i wypycham restem. Poczytaj o CQRS i JOOQ.

EL
  • Rejestracja:około 13 lat
  • Ostatnio:3 miesiące
0
Bambo napisał(a):

Ja dla każdego widoku na froncie mam osobnego dtosa, ale nie muszę już nic mapować z encji - jeśli muszę coś popchać po prostu do klienta, nie updatuje mi to stanu aplikacji to wyciągam z bazy dtosa bezpośrednio przez jakiś query service i wypycham restem. Poczytaj o CQRS i JOOQ.

Okej rzucę okiem.
U mnie problem jest jednak taki że mam hibernate'a (a w niektórych częściach jeszcze eksperymentalnie Spring Data JPA) i to samo w sobie wymusza już posiadanie klas Entity. Robiąc więc zwykłego select'a na wyjściu dostaję np. UserEntity które muszę przekonwertować żeby nie wypychać encji na widok. Czytałem artykuły tego typu:
https://smarterco.de/spring-data-jpa-query-result-to-dto/
z których wynika że można na wyjściu dostać DTO po zwykłym zrobieniu selecta ale takie egzotyczne rozwiązania mnie jakoś nie przekonują bo mam wrażenie że sprawdzają się tylko w prostych przypadkach.

Bambo
  • Rejestracja:ponad 10 lat
  • Ostatnio:7 miesięcy
  • Postów:779
0

Dlatego staram się jpa nie używać :). Możesz też porobić sobie widoki zmaterializowane.

EL
  • Rejestracja:około 13 lat
  • Ostatnio:3 miesiące
0

No tak, to prawda ale jednak wiele projektów hula na JPA i przypuszczam że do każdego select'a nie robi się widoków i jakoś to działa stąd też moje pytanie czy ma ktoś jakieś sprawdzone rozwiązania na to?

S8
  • Rejestracja:ponad 6 lat
  • Ostatnio:7 miesięcy
  • Postów:63
0

Ja sobie chwalę to rozwiązanie które wcześniej podlinkowales, czyli używanie konstrukcji "select new dto(...) from".

EL
  • Rejestracja:około 13 lat
  • Ostatnio:3 miesiące
0

A masz jakiś ciekawszy sposób niż tworzenie konstruktora ze wszystkimi polami i potem bindowanie to na zapytaniu?
W przypadku kilku pól nawet sobie wyobrażam użycie takie konstruktora natomiast jak mam powiedzmy klasę User, ona ma kilka pól typu imie, nazwisko itp oraz np. AdressDTO, SpecificDataDTO itp to musiałbym w tych wszystkich klasach dodatkowych też robić takie konstruktory i ten zwykły select byłby jakimś kosmicznie nieczytelnym tworem.

Bambo
  • Rejestracja:ponad 10 lat
  • Ostatnio:7 miesięcy
  • Postów:779
0

Może projekcje ?

S8
  • Rejestracja:ponad 6 lat
  • Ostatnio:7 miesięcy
  • Postów:63
0
eL napisał(a):

A masz jakiś ciekawszy sposób niż tworzenie konstruktora ze wszystkimi polami i potem bindowanie to na zapytaniu?
W przypadku kilku pól nawet sobie wyobrażam użycie takie konstruktora natomiast jak mam powiedzmy klasę User, ona ma kilka pól typu imie, nazwisko itp oraz np. AdressDTO, SpecificDataDTO itp to musiałbym w tych wszystkich klasach dodatkowych też robić takie konstruktory i ten zwykły select byłby jakimś kosmicznie nieczytelnym tworem.

Jak jest sporo konkretnych kolumn do pobrania to i tak zwykle trzeba je wszystkie wymienić w projekcji, więc dodanie samego wywołania konstruktora w zapytaniu nie wydaje mi się dużym problemem.
W przypadku gdy chcemy stworzyć kilka obiektów, zwykle robię to jak w odpowiedzi tutaj: https://stackoverflow.com/questions/40218903/hibernate-hql-multiple-new-objects
Też mam trochę wątpliwości, czy to jest najlepsze rozwiązanie, ale zwykle wychodziło jako najkrótsze.

W przypadku gdy liczba kolumn do pobrania jest bardzo dużo, to zwykle kończę z widokiem przykrywającym zapytanie i osobnym mappingiem na widok.

edytowany 1x, ostatnio: Seti87
Aleksander Brzozowski
  • Rejestracja:około 8 lat
  • Ostatnio:ponad 4 lata
  • Postów:26
0
Bambo napisał(a):

Ja dla każdego widoku na froncie mam osobnego dtosa, ale nie muszę już nic mapować z encji - jeśli muszę coś popchać po prostu do klienta, nie updatuje mi to stanu aplikacji to wyciągam z bazy dtosa bezpośrednio przez jakiś query service i wypycham restem. Poczytaj o CQRS i JOOQ.

Też staram się tak robić, szczególnie kiedy posiada się lomboka, to zrobienie tych dto jest bardzo proste i szybkie.
Jeżeli jakaś encja może posiadać kilka stanów, którym odpowiadają różne dto, to zrobiłbym ich tyle ile trzeba.

AL
  • Rejestracja:około 7 lat
  • Ostatnio:ponad 5 lat
  • Postów:84
0

A dlaczego nie używasz budowniczego? Jak masz lomboka to oznaczasz sobie klasę @Builder i nie musisz robić masy konwerterów, równie dobrze możesz zrobić taką mini fabrykę, gdzie po prostu uzupełniasz pola jakie chcesz. Tylko wtedy niektóre pola mogą przyjść jako 0 dla inta lub null dla obiektów/stringa więc na froncie musiałbyś sprawdzać czy jakiś element nie jest nullem.

Aleksander Brzozowski
Według tego podejścia to powinno się zrobić jedno dto, które posiada te same pola co encja, tylko niektóre są puste. To nie ma sensu, bo potem dostajesz taki model i zastanawiasz się czy to pole jest ustawione.
EL
  • Rejestracja:około 13 lat
  • Ostatnio:3 miesiące
0
Aleksander Brzozowski napisał(a):
Bambo napisał(a):

Ja dla każdego widoku na froncie mam osobnego dtosa, ale nie muszę już nic mapować z encji - jeśli muszę coś popchać po prostu do klienta, nie updatuje mi to stanu aplikacji to wyciągam z bazy dtosa bezpośrednio przez jakiś query service i wypycham restem. Poczytaj o CQRS i JOOQ.

Też staram się tak robić, szczególnie kiedy posiada się lomboka, to zrobienie tych dto jest bardzo proste i szybkie.
Jeżeli jakaś encja może posiadać kilka stanów, którym odpowiadają różne dto, to zrobiłbym ich tyle ile trzeba.

Wcześniej myślalem że robienie wielu DTO + konwerter dla każdego z widoków jest głupie bo sporo kodu podobnego powstaje ale z drugiej strony jak czytam że inni tak robią to zaczynam się sam zastanawiać że to w sumie może mieć sens i jest przynajmniej bardziej czytelne niż kombinowanie z jakimś jednym DTO żeby go na kilka widoków użyć.

Mam lomboka i buildera w projekcie i moje konwertery tak budują DTO albo Entity.
Mógłbym pozbyć się konwerterów i tworzyć te obiekty przez buildera w miejscach gdzie to potrzebuje, natomiast niektóre klasy są bardzo rozbudowane więc wolę to zamknąc w konwerterach.

Generalnie z tego co rozumiem to pomijając sposób z JOOQ (bo niestety już mam jpa w projekcie) to zostaje mi to samemu konwertować albo zrobić jakieś projekcje itp. i tak czy inaczej nie ma na to jakiegoś sprytnego wzorca który by pozwolił nie klepać aż tyle kodu a jednocześnie byłby bardzo czytelny.

QB
  • Rejestracja:ponad 9 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Lublin
  • Postów:170
2

Wydziel grupy pól które się powtarzają.
Np. w UserProfileDTO wydziel sobie atrybut UserDTO user, w którym masz te powtarzające się dane np. username, avatar.

Jeśli chcesz, żeby struktura zserializowanego w JSONie UserProfileDTO była płaska (np. nie chcesz pola user, tylko od razu username, password), to używasz adnotacji @JsonUnwrapped

Potem możesz sobie ten UserDTO tak samo komponować do innych DTO.

edytowany 2x, ostatnio: qbns
EL
  • Rejestracja:około 13 lat
  • Ostatnio:3 miesiące
0

Okej, dzięki bardzo!
Myślę że konwertery i pomysł @qbns są dla mnie wystarczające. Przy pobieraniu danych z bazy jeśli się okażę że sporo kolumn w danym momencie nie jest potrzebne to żeby nie zaciągać za dużo danych będę po prostu dodawać projekcje albo widoki. Tak czy inaczej myślałem że znajdę jedno konkretne rozwiązanie które będzie uniwersalne dla wszystkich przypadków ale jednak okazuje się że lepiej będzie mixować je w zależności od potrzeb. Dzięki.

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)