Wątek przeniesiony 2023-10-12 18:34 z Java przez Riddle.

Podział encji na domenowe i JPA

0

Rozdzielacie encje na te domenowe i JPA? Z jednej strony powinno się tak robić, żeby domena była czysta i nie wiedziała nic o frameworkach, z drugiej tworzy to trochę dodatkowego kodu i pochłania dodatkową ilość czasu. Szkoda, że Hibernate nie umie sobie wygenerować sam tych encji na podstawie obiektów domenowych.

3

Polecam nie używać JPA - problem się wówczas rozwiązuje.
Ale serio - dużo innych problemów też Cie ominie. Chyba, że chcesz zostać ekspertem od problemów z JPA - wtedy to co innego.
Proste alternatywy JOOQ i JDBI (nie JDBC).

1

Tak jak napisano - daruj sobie JPA.
Natomiast podział na encją domenowe i bazodanowe ma sens wtedy i tylko wtedy, gdy twoja domena mocno różni się od tabel w SQLu. Jeśli model domenowy to 1:1 to, co w bazie danych to nie widzę powodu, żeby kod duplikować bo tak napisano w książce.

0

Znaczy, nie wiem czy w ogóle słowo "podział" ma jakikolwiek sens, bo to sugeruje że jest jakaś relacja/reprezentacja między nimi, a to przecież są zupełnie inne byty które nie powinny mieć ze sobą nic wspólnego. Więc moim zdaniem zawsze jest sens je oddzielać, nie chcesz mieć tight-coupling na warstwę persystencji w swojej aplikacji.

Brzmi to trochę tak, jakbyś dla encji JPA z automatu robił jakiś odpowiedni w domenie (albo odwrotnie), a to w ogóle nie ma sensu. Powinieneś mieć zakorzenione z tyłu głowy że domena to jedno, a persystencja to drugie, one nie powinny być do siebie podobne.

I tytułem dygresji, może dodam że JPA jako warstwa abstrakcji na bazę jest raczej średna, i ja bym chyba poszukał czegoś innego.

1

Tak, zawsze. Najlepiej nie używać JPA, ale jak jakiś spring tutorial architect się upiera to chociaż oddzielać te 2 encje, bo utrzymywanie kodu, w którym JPA przeplata się z encjami logiką biznesową to koszmar i wieczne błędy.

wartek01 napisał(a):

podział na encją domenowe i bazodanowe ma sens wtedy i tylko wtedy, gdy twoja domena mocno różni się od tabel w SQLu. Jeśli model domenowy to 1:1 to, co w bazie danych to nie widzę powodu, żeby kod duplikować bo tak napisano w książce.

Z tym argumentem mam zawsze taki problem, że nigdy nie wiesz kiedy model przestanie być 1:1 i w pewnym momencie zrefactorowanie takiego kodu żeby te modele wydzielić może być drogą przez mękę.
A sytuacja, że modele przestają być 1:1 jest dosyć częsta w przeciwieństwie to np. mitycznego zmieniania DBMSa, które jest nieraz argumentem "za" używaniem JPA

3

Widziałem głupie błedy w aplikacjach gdzie były tylko encje JPA - wystawiane "na chama" przez rest.
I widziałem głupie błedy w aplikacjach gdzie ludzie poświęcili czas na wprowadzanie i mapowanie na DTO - czy jeszcze zabawnej na jakiś model domenowy.
W tym drugim przypadku zwykle pojawiają się jakieś gówniane automappery, ktore robią z przykrego przypadku - beznadziejny.
(np. nie da się łatwo wyszukać kto i gdzie ustawia pole, bo jest to robione mapperem przez fefleksje).

Btw @Riddle nie wiem co kierowało Tobą, że przeniosłeś to z działu Java. Nie dość, że JPA jest naprawdę specyficzne dla Javy to jeszcze wstyd trochę.

1

Znalazłem sposób na to. Całe mapowaniem przeniosłem do jednego pliku xml, dzięki temu encje domenowe mogą być czyste i nic nie wiedzieć o żadnym JPA. Został jedynie bezparametrowy konstruktor, ale może być prywatny

1
Nofenak napisał(a):

Znalazłem sposób na to. Całe mapowaniem przeniosłem do jednego pliku xml, dzięki temu encje domenowe mogą być czyste i nic nie wiedzieć o żadnym JPA. Został jedynie bezparametrowy konstruktor, ale może być prywatny

Brzmi jak wyleczenie bólu ręki amputacją. Podział nie jest po to, żeby nie było tych wrednych adnotacji, tylko:

  • domena może być bardziej zaawansowana np. używać zaawansowanych struktur danych. Model używany przez bazę jest często ograniczony, bo mapper baza <-> kod jest ograniczony
  • mieć elastyczność. Przykładowo w przypadku bazy musimy dbać o kompatybilność wsteczną. Model może być bardziej elastyczny i mogę sobie zmienić nazwę pola albo typ
  • domena nie koniecznie musi być używana przez bazę albo może być użyta w innym kontekście. Mając odzielonny kod możesz łatwo podmienić bazę np. z SQL na Redisa albo SQL na wywołanie API

Wrzucenie mapowania do pliku XML nic nie rozwiązuje a dodaje dużo nowych problemów jak utrzymanie XMLa, który jest jeszcze bardziej upierdliwy niż adnotacje. Jak chcesz automatyzacji to użyj mappera https://www.baeldung.com/java-performance-mapping-frameworks , którego można sie zawsze pozbyć jak się okaże, że gra nie jest warta świeczki

0
Nofenak napisał(a):

Znalazłem sposób na to. Całe mapowaniem przeniosłem do jednego pliku xml, dzięki temu encje domenowe mogą być czyste i nic nie wiedzieć o żadnym JPA. Został jedynie bezparametrowy konstruktor, ale może być prywatny

To nadal nie jest dobre rozwiązanie, bo nazwy pól i typy pól są uzależnione od siebie.

Nie mówiąc o tym, że nie każda encja JPA powinna mieć swój odpowiednik w domenie i odwrotnie.

0
slsy napisał(a):
Nofenak napisał(a):

Znalazłem sposób na to. Całe mapowaniem przeniosłem do jednego pliku xml, dzięki temu encje domenowe mogą być czyste i nic nie wiedzieć o żadnym JPA. Został jedynie bezparametrowy konstruktor, ale może być prywatny

Brzmi jak wyleczenie bólu ręki amputacją. Podział nie jest po to, żeby nie było tych wrednych adnotacji, tylko:

  • domena może być bardziej zaawansowana np. używać zaawansowanych struktur danych. Model używany przez bazę jest często ograniczony, bo mapper baza <-> kod jest ograniczony
  • mieć elastyczność. Przykładowo w przypadku bazy musimy dbać o kompatybilność wsteczną. Model może być bardziej elastyczny i mogę sobie zmienić nazwę pola albo typ
  • domena nie koniecznie musi być używana przez bazę albo może być użyta w innym kontekście. Mając odzielonny kod możesz łatwo podmienić bazę np. z SQL na Redisa albo SQL na wywołanie API

Wrzucenie mapowania do pliku XML nic nie rozwiązuje a dodaje dużo nowych problemów jak utrzymanie XMLa, który jest jeszcze bardziej upierdliwy niż adnotacje. Jak chcesz automatyzacji to użyj mappera https://www.baeldung.com/java-performance-mapping-frameworks , którego można sie zawsze pozbyć jak się okaże, że gra nie jest warta świeczki

Ale to i tak i tak tę zaawansowaną strukturę danych będzie trzeba jakoś zapisać w bazie, więc nie rozumiem tego argumentu. Jakiś konkretny przykład?
W XML też można zmapować pola o różnych nazwach, np userId -> id
Alternatywą jest utrzymywanie sporej ilości mapperów, pewnie jakiegoś frameworka do mapowania no i oczywiście osobnych modeli danych. Wolę jednego xmla

Riddle napisał(a):
Nofenak napisał(a):

Znalazłem sposób na to. Całe mapowaniem przeniosłem do jednego pliku xml, dzięki temu encje domenowe mogą być czyste i nic nie wiedzieć o żadnym JPA. Został jedynie bezparametrowy konstruktor, ale może być prywatny

To nadal nie jest dobre rozwiązanie, bo nazwy pól i typy pól są uzależnione od siebie.

Nie mówiąc o tym, że nie każda encja JPA powinna mieć swój odpowiednik w domenie i odwrotnie.

Nazwy pól nie są od siebie uzależnione, bo tak jak mówiłem można sobie mapować np. userId na id a z typami jest chyba podobnie
No wiadomo, nie wszystko trzeba zapisywać w bazie, nawet mam takich przykład u siebie w apce, mail - mam tylko encje domenową

W ogolę, to pomysł na tego xmla wziąłem z tej prezentacji. Gość zrobił coś podobnego w PHP w 16.50:

3
Grzyboo napisał(a):

Z tym argumentem mam zawsze taki problem, że nigdy nie wiesz kiedy model przestanie być 1:1 i w pewnym momencie zrefactorowanie takiego kodu żeby te modele wydzielić może być drogą przez mękę.

Czasem model przestaje się zgadzać, czasem nie. Zbyt wiele aplikacji widziałem, gdzie encje bazodanowe, obiekty domenowe oraz obiekty wystawione dla widoku były tym samym, żeby się zgodzić.
Pewne rzeczy można przewidywać - jak masz jakąś większą aplikację to podział "na zaś" może mieć sens, ale jak masz izolowany mikroserwis to koszt jego refaktoru jest niewielki - a i tak przy zmianie musisz go dokonać.

1 użytkowników online, w tym zalogowanych: 0, gości: 1