JPA Encje jak z nimi pracować ze swoim kodem?

0

W C# miałem wygenerowane klasy przez EF, robiłem partial classes i pisałem swoje metody, pola itd. dla tych obiektowych reprezentacji tabel.

Obecnie działam z JPA, który też mi generuje klasy(encje) z tabel, ale w javie nie ma partial classes. Jeśli zmienię coś w bazie, np. dodam kolumnę i znowu robię generowanie z tabeli na klasę, to cały plik jest nadpisywany i nie ma tam mojego kodu.

Jak sobie radzić z czymś takim? Zwłaszcza że kod się już pisze, a już struktura bazy na 100% będzie jeszcze ulegać zmianom. Mimo wszystko swoje metody i pola("tymczasowe" nie poziązane z bazą) już piszę dla tych klas. Nie chcę później przy kolejnym generowaniu wszystko stracić, albo mozolnie przepisywać tego.

0

Jakie IDE?
Jak aktualizujesz?

0

Eclipse Juno EE. Generuję poprzez kliknięcie drugim przyciskiem na project > JPA Tools > Generate Entities From Tables. Tam mam zdefiniowany connector do bazy, ustawienia JPA (sterownik itd.). Przy generowaniu wybieram dokładnie z jakich tabel i jakie relacje uwzględnić i otrzymuję wygenerowane Entities w podanym miejscu z adnotacjami JPA itd.

0

Netbeans nie nadpisuje - ręcznie dodany kod zostawia nienaruszony.
Może warto się przenieść?

0

Wolę zostać przy swoim IDE.
Jeśli ktoś wie jak sobie z tym poradzić, chętnie posłucham.

0

Widzę że wybrałeś podejście database first i generowanie klas poprzez reverse engineering. Można tak pracować, ale częstym podejściem jest odwrotna sytuacja, czyli tworzenie encji i generowanie z nich tabelek bazodanowych.

W twoim przypadku proponuję jednak nie modyfikować wygenerowanych encji (czyli zostawić tzw. głupie encje). Wydzielić osobną warstwę abstrakcji co będzie zajmować się logiką biznesową. Wtedy przy każdej zmianie tabelek będziesz mógł bez problemu przegenerować kod encji.

0

Dzięki za odpowiedź.
Korzystałem z różnych podejść już. Database first pozwala czasem na łatwiejsze modyfikacje bazy bez utraty danych. Natomiast najpierw tworząc w kodzie encje łatwiej się z kodem pracuje i częstym generowaniem bazy, kiedy program jeszcze nie jest w użyciu.

Twoje rozwiązanie nie jest złe, ale np. @NamedQuery gdzie miałbym umieszczać?

0

Tworzenie najpierw schematu bazy danych jest podejściem teoretycznie nieprawidłowym. W teorii baza danych powinna przechowywać model domenowy (encje), który jest tworzony wcześniej. W praktyce często się jednak zdarza że baza danych jest tworzona wcześniej. To zależy też od innych aspektów biznesowych.

Jednak chcąc mieć wygenerowany model encji i z nim sensownie pracować, trzeba się liczyć z pewnymi ograniczeniami. Nie wszystkie relacje da się poprawnie odczytać z samej struktury bazy danych. Jeśli mimo wszystko chcesz zastosować to podejście i generować encje, to proponuję dwa rozwiązania:

  1. Nie używać NamedQuery. W zamian zastosować Spring JPA Data (http://docs.spring.io/spring-data/jpa/docs/1.5.1.RELEASE/reference/html/) - jest to jedno z najlepszych narzędzi do aplikacji typu CRUD.

  2. Trzeba mieć w projekcie dwa osobne foldery - jeden ze źródłami, i tu encje będą mogły być modyfikowane przez ciebie. Drugi do generowania. Po każdym przegenerowaniu, należy skopiować przegenerowany plik java do katalogu ze źródłami i zaaplikować patcha z poprzedniej wersji tego pliku (zmienionego).

Osobiście polecam metodę 1, ale czasami i tak potrzeba robić zmiany w wygenerowanych encjach - wtedy robimy mix z metody 1 i 2.

Z drugiej strony jeśli nikt nie zmusza cię do tworzenia najpierw bazy danych i z niej generowania encji to poważnie bym się zastanowił nad zmianą podejścia (model domenowy pierwszy).

pozdrawiam,
K

0

Co w przypadku kiedy bazę generujemy z encji z kodu, z po jakimś czasie w aplikacji trzeba dodać dodatkową tablę lub kolumnę? Wygenerowanie bazy z encji w kodzie całą bazę wyczyści, czego się boję bo na 100% program będzie pod tym względem rozbudowywany. Natomiast jak generujemy z bazy, to z danymi nic się nie dzieje w bazie.

0

Bzdura. Update struktury tabel wcale nie kasuje ci danych. Jak nie ustawisz w konfiguracji "crate-drop" tylko "update" to nie będzie problemu.

0

Nie wyczyści. Jeżeli ustawisz odpowiedni sposób aktualizacji to kolumna zostanie dodana, o ile nie ma na niej ograniczenia NOT NULL. Dodawania tabel jest przezroczyste (o ile nie dodajesz nowych kolumn wskazujących na tą tabelę).

Inna sprawa to korzystanie z encji w kodzie - nie dobry pomysł właśnie z powodu zmian w strukturze bazy. Już lepiej trochę się napałować i dopisać sobie jakiś obiekt obudowujący albo pójść na całość pisząc odpowiednią klasę domenową i traktować encje jako DTO dla bazy. To oznacza dopisanie transformatora.

0

Ja z kolei rozwijam database-first, bo jest szybciej. Znacznie szybciej za pomocą odpowiedniego narzędzia wygenerować bazę danych, następnie wygenerować kod encji. Oczywiście wygenerowany kod nie będzie idealny np. należy zaktualizować sequences dla autoincrement jeśli występują itp. Ale co to za problem skoro mamy DDL wygenerowanej bazy. Z mojego doświadczenia constraints z DB są sensownie mapowane na JPA z automatu i bez sensu wykorzystywać do tego człowieka.

Co jeśli baza danych zmieni się np. dodam kolumnę, zmienię constraint lub coś usunę?
Po prostu modfikuje kod encji tak, aby był zgodny z bazą danych. Jest to trywialne i znacznie szybsze niż przegnerowywanie encji na nowo.

Nie wyobrażam sobie rozwijania średniej wielkości projektu składającego się z kilkudziesięciu tabel jako entity-first. Może w małej, trywialne aplikacji Rails / Grails, ale na pewno nie w biznesowej krowie w JEE.

I tak gdzieś musimy zrobić reverse engineering, pytanie gdzie. Czy chcemy zrobić reverse enginerring aby otrzymać diagram wygenerowanej bazy czy też z wygenerowanej bazy chcemy otrzymać encje.

0
Student911 napisał(a)

Nie wyobrażam sobie rozwijania średniej wielkości projektu składającego się z kilkudziesięciu tabel jako entity-first.

Dlaczego? Jest znacznie prościej niż ręczne dodawanie najpierw kolumn w bazie, a potem pól w klasach. hibernate.hbm2ddl.auto=update i jedziemy. Większym problemem jest zazwyczaj konieczność aktrualizacji procedur, funkcji, "native sql" i innych tego typu wynalazków. Dlatego we wszystkich projektach, które realizowalem używaliśmy dualnego podejścia.
W pierwszym kroku dodawaliśmy pole w klasie i to silnik ORM aktualizował strukturę bazy deweloperskiej.
Następnie aktualizowane były procedury, triggery, itp. rzeczy
W czasie wdrożenia przygotowujemy skryp aktualizujacy tabelę i inne elmenty i jest on odpalany. Na poziomie produkcji używamy hibernate.hbm2ddl.auto=validate.

Dzięki temu mamy szybką modyfikację baz developerskich i bezpieczną modyfikację produkcji.

0
Koziołek napisał(a):

Dlaczego? Jest znacznie prościej niż ręczne dodawanie najpierw kolumn w bazie, a potem pól w klasach. hibernate.hbm2ddl.auto=update i jedziemy.

IMO, szybciej jest użyć narzędzia GUI do generowanie kolumn np. dla PostgreSQL jeśli od początku chcę zaprojektować całą bazę lub grupę tabel niekoniecznie powiązanych z obecnymi strukturami.
http://www.sqlpower.ca/page/architect-demos
Czy jak rozwijasz dużą aplikację code-first od początku zaczynasz od utworzenia klasy? Następnie dodajesz do niej odpowiednie adnotacje? Czy masz do tego odpowiedniej jakości narzędzie GUI, które powoduje, że nie musisz ręcznie pisać tego kodu, w którym widzisz relacje między tabelami, tak jak widać tabele na diagramie ERD. Czy to narzędzie GUI pokazuje od razu relacje między tabelami, które zostaną wygenerowane? Z jakiego IDE korzystasz tak, aby wygodnie generować code-first w JPA, najlepiej graficznie, bo IMO nieprzyjemne jest klepanie encji, a każda z nich ma z reguły kilkanaście linii kodu. Chyba nie opłaca się robić to ręcznie z wyjątkiem drobnego dostosowania do własnych potrzeb.

Większym problemem jest zazwyczaj konieczność aktrualizacji procedur, funkcji, "native sql" i innych tego typu wynalazków. Dlatego we wszystkich projektach, które realizowalem używaliśmy dualnego podejścia. 

To zawsze będzie problemem. Ale jak odpowiednio zarządza się zmianami to nie ma problemu.

W pierwszym kroku dodawaliśmy pole w klasie i to silnik ORM aktualizował strukturę bazy deweloperskiej.

Bawiłem się w podobny sposób programując mały projekt w GRails i było to efektywne. Ale jakoś wole najpierw zaprojektować bazę.

  Następnie aktualizowane były procedury, triggery, itp. rzeczy
W czasie wdrożenia przygotowujemy skryp aktualizujacy tabelę i inne elmenty i jest on odpalany. Na poziomie produkcji używamy `hibernate.hbm2ddl.auto=validate`. Dzięki temu mamy szybką modyfikację baz developerskich i bezpieczną modyfikację produkcji.

Ja bezpieczniej się czuje, gdy wykonuje ręcznie odpowiedni DDL najpierw na maszynie deweloperskiej, a następnie produkcyjnie.

Z drugiej strony kiedyś na pewno muszę spróbować entity-first, bo czegoś nowego się nauczę. Code-first wydaje mi się to nienaturalne w projektowaniu relacyjnych baz danych, które są wręcz stworzone tak, aby myśleć o nich jako o tabelach, a nie encjach.

Zgadzam się, że jak dodaje np. dodatkową tabelkę to pomoc ORMa może nie zaszkodzić, jednak ALTER TABLE x ADD COLUMN y to też nie jest aż taki straszny problem.

0

Ja tam narzędzi do budowania za pomocą klikania nie używam. Z kilku powodów. Po pierwsze są strasznie powolne. Po drugie nie są elastyczne. Po trzecie żadne z nich nie wyprodukuje czystego i eleganckiego kodu. kodowanie zaczynam od napisania klasy - nazwa + pola. W tym JEDNO zaadnotowane jako @Id. Później dwa szybkie skróty klawiaturowe i mam gettery/settery. Po to znam IDE by nie użerać się z powolnymi narzedziami do budowy za pomocą myszy. Tak, mysz jest najpowolniejszym rodzajem narzedzia do wprowadzania danych.

Poza tym mając kod mogę od razu przystąpić do pisania logiki, testów i rozwiązań olewając bazę danych. Obecnie realizuję, trochęna boku, projekt gdzie bazy danych jeszcze nie mamy, bo nie ma decyzji co do tego gdzie będzie apka stała i co tam będzie rzeczywiście dostępne (mysql, postgres, mongo, czy oracle EE). I jakoś żyję. Kod piszę, testy robię, a baza... to tylko plugin.

0

@student911 tylko że ty stosujesz tutaj podejście database-centric, które moim zdaniem nie jest generalnie specjalnie dobre. Moim zdaniem dużo lepszym podejściem jest pisanie po prostu kodu systemu z danymi w postaci czysto obiektowej, nie myśląc w ogóle o tym jak to się potem zmapuje do bazy danych.

0
Koziolek napisał(a)

Po pierwsze są strasznie powolne. Po drugie nie są elastyczne. Po trzecie żadne z nich nie wyprodukuje czystego i eleganckiego kodu. kodowanie zaczynam od napisania klasy - nazwa + pola. W tym JEDNO zaadnotowane jako @Id. Później dwa szybkie skróty klawiaturowe i mam gettery/settery. Po to znam IDE by nie użerać się z powolnymi narzedziami do budowy za pomocą myszy. Tak, mysz jest najpowolniejszym rodzajem narzedzia do wprowadzania danych.

To zalezy.

Nie zgadzam sie z tym, w przypadku database-first. IMO reczne pisanie DDL bazy danych jest znacznie powolniejsze niz wyklikanie diagramu ERD. Nie spotkalem sie jeszcze z dobrym IDE, ktore generuje solidny DDL. Tu klikanie jest znacznie bardziej efektywne. Poza tym dla klienta / menadzerow diagramy ERD sa znacznie latwiej zrozumiale niz kod obiektowy, a jest to bardzo wazne na etapie, gdy wymagania nie sa stabilne. A w takiej sytuacji diagram musze sobie wygnerowac z istniejacej bazy, co jest mniej efektywne niz go wyklikanie (chociazby dlatego, ze automat brzydko ulozy encje na dokumencie np. do wydruku, a bywa ich bardzo duzo). BTW. Moze cos polecicie co wspomaga pisanie DDL na tym poziomie co Java: dobre IDE dla PostgreSQL?

Co do kodu Javy to sie zgadzam, tylko klawiatura (przypadek z code-first). Myszy praktycznie nie uzywam.

Jednak encje dla gotowej bazy i tak szybciej wygenerowac, jedyne co trzeba zrobic wczesniej to zmodyfikowac szablon IDE dla tego typu obiektow (ale to i tak kazdy robi).

Poza tym mając kod mogę od razu przystąpić do pisania logiki, testów i rozwiązań olewając bazę danych. Obecnie realizuję, trochęna boku, projekt gdzie bazy danych jeszcze nie mamy, bo nie ma decyzji co do tego gdzie będzie apka stała i co tam będzie rzeczywiście dostępne (mysql, postgres, mongo, czy oracle EE). I jakoś żyję. Kod piszę, testy robię, a baza... to tylko plugin.

W moim projekcie bylo zupelnie inaczej: bylo do razu wiadomo, ze dostepny bedzie Postgres, bylo to budowanie nowego projektu na bazie starego projektu, bo przepisanie nie bylo mozliwe. Jednak potezna czesc apliacji mozna bylo oddzielic i database oriented design byl dla nas o wiele wygodniejszy. W twoim przypadku jednak tez poszedlbym w code-first. Dzieki za fajny przyklad z zycia wziety.

@student911 tylko że ty stosujesz tutaj podejście database-centric, które moim zdaniem nie jest generalnie specjalnie dobre.

IMO glowna zaleta code-first to tzw. cross-platformowosc, w ktora osobiscie i tak az tak bardoz nie wierze. Bo przenosnosc bedziemy miec tylko na poczatku. W momencie, gdy w projekcie pojawia sie np. procedury skladowe i tak zejdzie to na dalszy plan.

W przypadku, gdybym chcial uzywac bazy NoSQL tez wybralbym code-first.

Panowie: dzieki za uswiedomienie mi waznosci zagadnienia code-first.

0
Student911 napisał(a)

IMO reczne pisanie DDL bazy danych jest znacznie powolniejsze niz wyklikanie diagramu ERD. Nie spotkalem sie jeszcze z dobrym IDE, ktore generuje solidny DDL. Tu klikanie jest znacznie bardziej efektywne.

Chętniew urządzę małe zawody. Ty z klikaczką ERD, kontra ja z Ideą i klepaniem klas. Mamy gotowy model na papierze... Sądzę, że nawet musząc odpalić generowanie DDLa w hibernate bedę pierwszy. Co do IDE to tylko Idea :) Z SQLem też daje radę.

Student911 napisał(a)

gdy w projekcie pojawia sie np. procedury skladowe i tak zejdzie to na dalszy plan.

dlatego też jak nie masz w ogole bazy danych to nie produkujesz procedur.

0
Koziołek napisał(a):

Co do IDE to tylko Idea :) Z SQLem też daje radę.

Mam zamiar pobrać Ultimate Demo i wypróbować. Jednak na 1 rzut oka w przypadku encji JPA trafiłem na gorsze wsparcie dla pisania zapytać JPQL niż w NetBeans w domyślnej konfiguracji: albo brakowało mi odpowiedniego pluginu (obstawiam raczej to drugie). Poza tym na dzień dobry nie był dostępny ładny i szybki dostęp do ustawień serwera aplikacji np. szybki dostęp do Server Log, czy możliwość szybkiego sterowania serwerem aplikacji GlassFish: włączania / wyłączania aplikacji, zarządzania zasobami itp. Pewnie też zabrakło pluginów. Muszę poświęcić więcej czasu na konfigurację. Miałem z kolei mega poztywne wrażenie w przypadku Android Studio i Javy SE. Nie wyobrażam sobie też rozwijania aplikacji Grails bez Idea. Wkrótce poznam to IDE lepiej, jednak początkowo na 1 rzut oka w przypadku JEE i GlassFisha NetBeans wypadło lepiej (pewnie dlatego, że znam słabiej, a w naukę nowego narzędzia trzeba zainwestować).

Koziołek napisał(a):

dlatego też jak nie masz w ogole bazy danych to nie produkujesz procedur

Tak, ale jednak bywają sytuację, że znacznie efektywniej napisać procedurę, a ORM i przetwarzania na poziomie serwera aplikacyjnego jest skrajnie nieefektywne.

0

@student911, brakowało, bo jest trochę inaczej rozwiązane niż w NB czy Eclipse. Też na początku się gubiłem. Potem jak już opanowałem to z górki.

Student911 napisał(a)

że znacznie efektywniej napisać procedurę, a ORM i przetwarzania na poziomie serwera aplikacyjnego jest skrajnie nieefektywne.

W bardzo, bardzo specyficznych przypadkach, a i to da się zrobić poprzez odpowiednią architekturę kodu.

interface NeedHighPerformanceFor{
    void thisUseCase(Object...params);
}

I teraz czy implementacją będzie wołaniem bazy danych czy też naklepiesz coś w Javie nie ma znaczenia. Migracja z jednej bazy na inną? W praktyce nie dotyka kodu, bo tylko zmieniasz konfigurację DI by użyła innego beana. Testowanie - mock i po problemie.

0

IMO glowna zaleta code-first to tzw. cross-platformowosc, w ktora osobiscie i tak az tak bardoz nie wierze

Ja bym powiedział że główna zaleta to elastyczność w kwestii projektowania architektury aplikacji :) Bo pisząc kod skupiasz się na tym co ci jest potrzebne i na tym żeby sensownie tą aplikację napisać. W efekcie, szczególnie dla aplikacji które nie są jasno zdefiniowane i są trochę prototypowane albo pisane mocno przyrostowo, nie przejmujesz się w ogóle tym że non-stop zmieniasz strukturę klas encyjnych. Brakuje ci pola? Dodajesz. Potrzeba wydzielić jakiś poziom abstrakcji? Wydzielasz. Trzeba rozbić klasę na mniejsze? Rozbijasz. Trzeba zrobić jakieś delegacje? Robisz. Okazuje się że jakieś pola są zbędne? Usuwasz. Jakieś pole jednak lepsze będzie jako enum? Zmieniasz.

W podejściu database-first to jest trochę trudniejsze bo musisz za każdym razem edytować strukturę bazy i czasem robić spory misz-masz. Bo wydzielenie nadklasy w javie to jest jeden klik w IDE. W zrobienie nadklasy na poziomie bazy danych? ;) W efekcie widywałem już takie sytuacje że strukturę bazy ktoś zrobił na początku projektu a potem, mimo że wymagania ewoluowały, trzymali się tej struktury jak tylko mogli. W efekcie cuda na kiju się działy po stronie aplikacji bo struktura bazy zwyczajnie nie pasowała do wymagań.

0
Koziołek napisał(a):

W bardzo, bardzo specyficznych przypadkach, a i to da się zrobić poprzez odpowiednią architekturę kodu.

A co zrobisz z takim przypadkiem:
Masz bardzo dużo danych, których nie potrzebujesz przesyłać do aplikacji, chcesz je jedynie wygenerować na ich podstawie coś nowego np. linie księgujące na podstawie pewnych danych wejściowych (załóżmy, że jest ich bardzo, bardzo dużo). IMO procedura składowa nadaje się tutaj wyśmienicie, ponieważ nie muszę przesyłać danych do ORMa i serwera aplikacji - jest to zwyczajnie zbędne. Prosta procedura wsadowa po stronie bazy sprawdza się idealnie. I jest szybciej.

Tak samo cykliczne czyszczenie historycznych niepotrzebnych danych np. tablic z logami realizowałbym po stronie procedury składowej, ponieważ uważam że bez sensu jest przesyłać te dane do aplikacji i przetwarzać jako obiekty. Co najwyzej w aplikacji utworzyłbym sobie EJB Timer Service, która z odpowiednią częstością wołałaby procedurę składową. :)

0

Ale to nadal jest szczegół implementacyjny. Jak ci się zmieni sposób logowania na plikowy (bo coś tam), czy na bazę nosqlową (bo modne i lepiej się do tego nadaje) to ciebie jako programisty nie powinno obchodzić jak to będzie realizowane gdy chcesz uruchomić use case "czyszczenie logów":

class CleanLogUC implements CleanLogInBoundary{
    private CleanLogEntry cle;

    public CleanLogResult cleanLog(DateTime before){
       CleanLogResult clr = CleanLogResult.newOne();
       clr.addValidationResults(validate(before));
       if(clr.isValid()){
            clr.addResult(cle.cleanLog(before));
       }
       return clr;
    }

}

I teraz czy CleanLogEntry.cleanLog oznacza operację na plikach, bazie danych, czy też wysłanie brygady luddystów w celu spalenia serwerowni nie jest już istotne. Jako programista zaimplementowałeś funkcjonalność czyszczenia logów. Co więcej CleanLogEntry może zaimplementować ktoś na drugim końcu świata w zupełnie innej technologii, bo masz separację. To samo dotyczy dowolnej innej operacji na danych.

Co to oznacza w praktyce? Ano to, że można za interfejsem CleanLogEntry może być już cokolwiek w zupełnie innym kontekście. Chociażby coś takiego jak klient webservice, a sam webservice to będzie procedura składowana > http://docs.oracle.com/cd/A97688_16/generic.903/b10004/plsqlservices.htm
Ale to już jest szczegół implementacyjny. Ty swoją robotę zrobiłeś. Aplikacja czyści logi. Jak? Tak jak akurat są składowane. Jak są składowane? A tak jak sobie skonfigurujesz.

Na tym polega "magia" code-first.

0

Szczerze mówiąc to nie widzę tego podejścia code-first.

Pierwsza wersja - do pierwszego wdrożenia - OK, chociaż nie wiem na ile JPA/Hibernate pozwala na definiowanie elementów specyficznych dla konkretnego systemu baz danych (klucze klastrujące, partycjonowanie, warunki na polach, indeksy wektorowe, zapytania rekurencyjne, pola XML etc).

Poprawki na danych produkcyjnych generowane automatem? To albo jakieś SF albo bazy danych na poziomie SQLite (LocalStorage).

  • skrypt aktualizujący trzeba napisać ręcznie - co już tu było wspomniane
  • jeśli tak, to trzeba go przetestować
  • łatwo o pomyłkę, jeśli inaczej baza była modyfikowana do developmentu a inaczej do testów
  • przy dużych tabelach, szczególnie powiązanych przez FK trzeba czasami użyć różnych sztuczek żeby zaktualizować strukturę (np. robić to partiami albo przy wyłączonych triggerach albo dla niektórych klientów) - JPA/Hibernate to potrafi?

W Ruby można pisać własne migracje:
http://guides.rubyonrails.org/migrations.html

A w JPA/Hibernate?

0
vpiotr napisał(a)

łatwo o pomyłkę, jeśli inaczej baza była modyfikowana do developmentu a inaczej do testów

To po co testy skoro testują coś innego niż to co developowano?

Co do reszty zarzutów, to JPA jest generyczne, zatem nie wspiera specyficznych rozwiązań. Co zaś tyczy się migracji to używa się raczej liquibase. Znacznie lepiej dopasowane narzędzie.

0

U mnie flyway do migracji wszystkich rodzajów baz.
Jeśli chodzi o Code first to:

Fajnie jest pisać algorytmy na obiektach nie myśląc o bazie jednak jak tego nie robić jeśli za chwile te obiekty stają się odzwierciedleniem tabel...i właśnie to jest cało zło, dlaczego tworzymy naszą logikę biznesową w ten sposób. Czy nie powinno być tak, że nasza logika składa się ze struktur które są ogólne - biznesowe, a nie żadne entity. Oczywiście musi istnieć system zapisu stanu naszych obiektów biznesowych (agregatów) ale to nie znaczy , że nasz CustomerBiznesObject jest encją.

W takiej sytuacji Code first ma sens. Oczywiśce nikomu się nie chce tworzyć jednej hierarchii obiektów biznesowych + osobna hierarchia bazodanowa (Ports and Adapters)

Ostatnio miałem do czynienia z projektem w którym zmienił się model bazy danych bo stary był niewydajny. Część tabel uległa rodzieleniu, część się scaliła itp...oczywiście musiałem poprawić wszystkie zapytania w systemie co nie było wielkim zaskoczeniem, ale dlaczego na boga musiałem przepisywać algorytmy biznesowe które korzystały z tych encji w starej postaci...nie tak powinno być

0
Koziołek napisał(a):
vpiotr napisał(a)

łatwo o pomyłkę, jeśli inaczej baza była modyfikowana do developmentu a inaczej do testów

To po co testy skoro testują coś innego niż to co developowano?

Chcesz powiedzieć że w tym fragmencie poniżej nie przewidujesz żadnych testów?

Koziołek napisał(a):

W czasie wdrożenia przygotowujemy skryp aktualizujacy tabelę i inne elmenty i jest on odpalany. Na poziomie produkcji używamy hibernate.hbm2ddl.auto=validate.

Edit:
Oba narzędzia (Liquidbase, Flyway) wyglądają na to że pomagają w migracji, ale Liquidbase z tego co przeczytałem umożliwia także porównanie dwóch schematów, więc wspiera też database-first.

0
vpiotr napisał(a)

Chcesz powiedzieć że w tym fragmencie poniżej nie przewidujesz żadnych testów?

Oczywiście, że przewiduję. Tyle tylko, że zachowana jest spójność pomiędzy tym co dzieje się na środowisku testowym (skrypt), a produkcją (skrypt). Automatyczna aktualizacja jest tylko na poziomie deweloperskim i tylko w ograniczonym zakresie. Chcemy zrobić to szybko i tyle. Nadal programista powinien przygotować skrypt (migrację za pomocą liquid) i nadal powinien go przetestować. Jednak jeżeli chcemy szybko dostarczać wartość biznesową to w pierwszym kroku powinniśmy odpuścić sprawy związane z DB. Niech sama się zaktualizuje i nie przeszkadza.
Co ciekawe jeżeli w trakcie takiej automatycznej aktualizacji na poziomie deweloerskim napotkamy jakiś problem to już mamy zrobiony pierwszy test. Wiemy, że naiwna aktualizacja za pomocą skryptu nie będzie wystarczająca.

Szczery napisał(a)

W takiej sytuacji Code first ma sens. Oczywiśce nikomu się nie chce tworzyć jednej hierarchii obiektów biznesowych + osobna hierarchia bazodanowa (Ports and Adapters)

Ta niechcica to pewien problem, ale z drugiej strony jest to kod, za który ktoś będzie nam wdzięczny. W dodatku mamy narzędzia pozwalające na weryfikację czy nie nastąpiło użycie klas-encji w kodzie biznesowym.

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