Uzycie bazy danych H2/Derby z JPA w JavaFX +Spring -> czy uzywamy dodatkowych Modeli ?

0

Moje pytatnie dotyczy tego czy w aplikacji desktopowej, korzystajacej z jakiejkolwiek lokalnej bazy danych stosuje sie dodatkowa wartwe modelu, czy moze od razu entity.

Przyklady jakie znalazlam w necie uzywaja od razu obiektow bazodanowych. Jest to o tyle klopotliwe w przypadku javyFX ze ogranicza uzycie ObservableProperties. Dlatego zastanawialam sie nad owrapowaniem POJO w JavaFXowa klase Modelu, ktora bym ladowala do Tabel, List itd...
Pytanie tylko czy to ma sens ? I jak z zarzadzaniem ramem.

Uzycie entities powoduje ze za kazdym razem, przy jakiejkolwiek akcji musze czyscic liste po czym na nowo zaciagac wszystkie obiekty. Natomiast w przypadku uzycia wrapperow co prawda nie czyszcze za kazdym razem calej listy, ale mam nieco wiecej weryfikacji. Co z kolei bedzie na pewno nieco dluzsze czasowo.

Jakies porady jak ten temat ugryzc ?

0

Nie wiem czy dobrze rozumiem, ale czy chodzi Ci o DTO? Są to pośredniczące obiekty, do których mapujesz interesujące Cię właściwości encji. Przydaje się do tego modelmapper.

0

Tak chodzi mi o DTO, w aplikacji ktora korzysta z jakiegos Zewnetreznego API normalnym jest ich uzycie i jest to bardzo wygodne. Zastanawiam sie jednak czy tak samo oplaca sie to robic w aplikacji z lokalna baza danych w JavieFX ktora zamiast normalnych pol uzywa swoich ObservableProperties czesto. Czy jednak clear i reload zostawic.

Bo tu pojawia sie kolejne pytanie, Mianowicie o Referencje. Jak nimi zarzacac w takim wypadku. Rozumiem ze musze dla kazdej klasy nadpisac metody equals i hashCode ?

0

Czytałem sobie ostatnio o tym i zastosowałem nawet w swoim prywatnym projekciku i DTO przydają się także przy ograniczaniu właściwości wysyłanych do widoku, w Twoim przypadku do interfejsu apki. Dzięki temu masz już w widoku tylko to co chcesz.

0

no tak, ale z kolei tworze nowa warstwe do ktorej musze zaladowac obiekty i przeszukiwac listy, bu updateowac istniejace. Mam w javieFX spory problem z zarzadzaniem RAM i GC nie czysci obiektow z referencjami. Wiec przy pobraniu nie moge ich tak po prostu za akzdym razem mapowac do nowych obiektow dto. Bo te stare zostana niestety. Wtedy lepszym wydaje mi sie ovrapowanie i po prostu po pobraniu z bazy listy obiektow, przeszukanie wraperow w poszukiwaniu odpowiedniego. Ale to znowu jest narzut czasowy.

0

już było..
Dto - stosować czy nie

0

Próba wyświetlania encji bazodanowych w aplikacji JavaFX to pomysł chybiony i fatalny w skutkach. Tak się tego nie robi.
Przemapować encje musisz ale nie do obiektów typu dto tylko do takich obiektów, które będą elegancko współgrały z FXowymi kontrolerami - czyli opakowujemy własności obiektów w odpowiednie properties, kolekcje wrappujemy w observable, innego wyjścia (sensownego) nie ma. W każdym innym przypaku kończy się to pisaniem tony metod do wyświetlania tych obiektów w tabeli, w listView, etc.

Mam w javieFX spory problem z zarzadzaniem RAM i GC nie czysci obiektow z referencjami.

Bo tu pojawia sie kolejne pytanie, Mianowicie o Referencje. Jak nimi zarzacac w takim wypadku. Rozumiem ze musze dla kazdej klasy nadpisac metody equals i hashCode ?

Przynam szczerze nie bardzo wiem co ma equals i hashCode do referencji a co one jeszcze do RAMu, do sterty to i może...
Napisz jak się objawia ten twój problem z GC w JavaFX bo popełniłem w tej technologii kilka aplikacji (jako chyba jedyny w Polsce nawet jedną komercyjną) i nigdy nie doświadczyłem żadnych problemów. Najlepiej pokaż jakiś zrzut z flight recordera, zrzut pamięci, cokolwiek, co pokazałoby problem.

0

Mowiac DTO w tym kontekscie mialam na mysli wlasnie obiekty z ObservableProperties.. Observable list i inne takie JavaFXowe.. dlatego w temacie nazwalam to Modelem.

A co ma equals iHash code.. juz tylumacze.

Moje obiekty zawieraja wiele referencji do innych obiektow. I pobierajac je z bazy uzywajac Hibernate.Instaciate().. nie jestem Pewna czy Obiekt A o Id1 jako pole w innym obiecie bedzie tym samym obiektem, co taki pobrany razem z Lista obektow.

Dajmy na no.. Przyklad z tylka.... Pobieram i wyswietlam na 2 listach, liste Nauczycieli i liste Studentow. Kazdy Student ma pole ulubionyNauczyciel. I teraz kiedy bede chciala wyswietlic tego ulubionego nauczyciela, czy zrobic na nim jakiekolwiek zmiany, to to nie bedzie ten sam Nauczyciel co na Liscie Nauczycieli.

Bylby nim na pewno gdybym gdzies sobie przechowala te liste nauczycieli jako cache, i majac Id Nauczyciela, pobrala go sobie z tego Cache'u. Wtedy na pewno mowilibysmy o tej samej referencji.

0

Czy pole ulubionyNauczyciel to jakieś id?

Bo jeśli tak to lepiej użyć tutaj relacji 1 nauczyciel (jest tym ulubionym) dla - wielu uczniów. Wiec relacja OneToMany skoro i tak używasz HIbernate'a.
Będziesz miała pewność, że ten ulubiony nauczyciel po pobraniu listy jest tym kim trzeba. Po to są relacje.

0

Nie no.. uzywam tam relacji OneToMany. Bardziej mi chodzi o referencje do obiektu. Bo jako obiekt w pamieci to nie bedzie to samo. Tym bardziej po przemapowaniu. Stad tez pomysl nadpisania equal i hashcode, by byc pewna ze w razie czego przy porownywaniu dostane true.

Chodzi o to ze wywolanie :

List<Nauczyciel> list = repositoryN.getAll();

A nastenie:
Nauczyciel nu= repositoryStudent.getOne(1).getUlubuony();

I teraz nie do konca jestem pewna czy bez nadpisania equals i hashcode, list.constans(nu) zwroci nam true. A nawet jesli zwroci to zgadzamy sie ze w pamieci to beda 2 rozne obiekty ?

A teraz przy mapowaniu ich na klasy NauczycielFX... to mapujac liste za kazdym razem uzyje New NauczycielFX. I to samo tworzac StudentFX i jego pole ulubionyNauczyciel.

Tak wiem jestem chaotyczna ale mam nadzieje ze teraz rozumiecie co chce powiedziec.

0

Żeby to w miarę bezproblemowo działało to flow w aplikacji jest mniej więcej taki:
Wyciągasz dane z bazy, mapujesz do obiektów, które da się wyświetlić (trzymasz w tych obiektach oczywiście jakieś id z bazy żeby było wiadomo co jest do czego), o tych pobranych z bazy zasadniczo możesz zapomnieć. Kończysz transakcję bazodanową, obiekty są w stanie detached, aktualizujesz widok i jest ok.
W razie konieczności zapisania czegoś do bazy:
Otwierasz transakcję, na bazie id z obiektu w widoku wyciągasz odpowiedni obiekt z bazy, robisz co trzeba, zapisujesz, zamykasz transakcję, mapujesz zmienione obiekty z powrotem do takich, które da się wyświetlić, aktualizujesz widok.
I tyle.
Jak zaczniesz się bawić w otwarte zbyt długo transakcje, aktualizowanie encji w przypadkowych momentach, albo co gorsza w cachowanie encji po stronie aplikacji i ich mergowanie przy kolejnej transakcji to popłyniesz.
Wydajnością się nie przejmuj na ten moment. Dojdź w aplikacji do momentu, w którym powyższy flow działa bez problemu, wszystko się zapisuje i masz kontrolę nad tym co się dzieje. Jak zmierzysz, że wydajność jest niezadowalająca to wtedy można myśleć o jakimś cache czy innym sposobie na poprawę działania.

Jeżeli chodzi o pisanie equals i hashCode dla encji to: https://thoughts-on-java.org/ultimate-guide-to-implementing-equals-and-hashcode-with-hibernate/

Nie opieraj logiki aplikacji o encje, jak masz w aplikacji jakiś skomplikowany przepływ danych to wstaw dodatkową warstwę pomiędzy kontroler a repozytorium który ci ogarnie kwestię mapowania, transakcji, etc. Jak flow jest prostyi polega tylko na wyciąganiu z bazy, wyświetlniu i edycji to od biedy nawet w kontrolerach można taką logikę zawrzeć.

Co do pytań - będą to dwa różne obiekty, equals napisany tak jak w linku powyżej da radę. Przy mapowaniu, trzeba zadbać o jakieś połączenie pomiędzy obiektem wyświetlanym a encją, np id encji.

0

No wlasnie mam mapowanie w fasadzie. Kwestia jest tylko taka, ze mam naprawde sporo tych polaczen, i wczensiej juz przy tej aplikacji mialam problem robiac list Clear, ze te obiekty nigdy nie byly czyszczone (efekt, kazde "czyszczenie" to przyrost 300MB danych :D)

Czyli mowisz ze nie warto robic czegos takiego:
ObservableList<ObjektA_FX> listFX.

I gdy aktualizuje liste, to streamuje te obiekty i mapuje do istniejacych alby nie rezerwowac nowej pamieci ??

A w przypadku wlasnie tych referencji. Mapowac je z uzyciem new object i wsadzam pola z danych. Czy majac aktualna liste wyszukuje na niej elementu o tym ID i to wsadzam jako referencje ?

Tutaj jest link to mojego postu odnosnie problemow z pamiecia : Usuwanie z pamieci zagnieżdżonych obiektów Java

0

Jak się nie czyści to widać coś trzyma referencję, trudno wywróżyć co. Przejrzałem mniej więcej kod z podlinkowanego tematu - może problem jest gdzie indziej:
Tam miałaś przykład, w którym trzymałaś cały czas referencję do kontrolerów, one mają referencje do list, do tego jakieś listenery i się może okazać, że nie ma co czyścić bo wszystko jest pospinane. Bez kodu ciężko będzie pomóc. Jeżeli robisz list.clear() a masz do niej podpięty listener to siłą rzeczy on zacznie działać w momencie usuwania i coś pamięci urośnie, jeżeli ma gdzieś referencje do obiektów z listy to efekt może być odwrotny do zamierzonego. Spróbuj ograniczyć czas życia obiektów. Jak robisz loader.getController() to nie zapisuj nigdzie referencji do tego kontrolera, powninien się zutylizować jak tylko dany widok przestanie być aktywny. Jeżeli nie to znaczy, że coś jeszcze trzyma referencję.
Podrzuć kod. Będziemy radzić :D

0

Akurat same kontrollery to byl moj najmniejszy problem. Ostatecznie poradizlam sobie trzymajac stale instancje kontrolera i jedynie ladujac ja do odpowiedniego widoku. Plus byl taki, e nie musialam za kazdym razem ladowac FXML'a. Oszczednosc czasu i przestrzeni. Problem byl w obiektach samego drzewa do wyswietlania. I probowalam wraz z metodami clearujacymi. i po wynulowaniu wszystkiego nadal nie dzialalo. Obiekty zostawaly. Ale to bede jeszcze prboowala rozwiazac Na razie przepisuje te aplikacje na baze danych, ze wzgledu na zarzadzanie spojnoscia danych. Stwierdzilam ze jednak z uzyciem bazy bedzie wygodniej. Stad tez wlasnie ten temat. Zastanawiam sie jak to najlepiej rozwiazac od strony modelu.

Czyli ostatecznie... Mam nie bawic sie w przeszukiwanie list by znalezc referencje. Tylko w mapowaniu tworzyc na chama new TargetObject tak ?

0

Pracę z bazą z poziomu apki w FX opisałem już najlepiej jak umiałem we wcześniejszym poście. Jeżeli tak to rozumiesz to tak.

0

Jedna rzecz mi nie daje w tej sytuacji spokoju. A konkretnie zasadnosc uzycia tej bazy danych. Bo w tej sytuacji mam baze na dysku (lub w pamieci... w zasadzie rozwazalam opcje bazy in memory i tylko robic zrzuty jako SAVE) i w pamieci obiekty JavaFXowe. Do tego dochodzi narzut czasowy zwiazany z mapowaniem.

Jest jeszcze jedna kwestia zwiazana z mapowaniem.
Obiekty maja bewne pole typu boolean. Ale to pole, moze byc TRUE tylko dla jednego obiektu w danej grupie. W tej sytuacji, robiac update na tym obiekcie i wstaiwajac to pole na TRUE, pozostale elementy musze ustawic na FALSE i wszystkie je zwrocic i przemapowac. usunac z listy poprzednie a nowe wlozyc...

0

Jeżeli zastanawiasz się nad sensem wrzucania tego do bazy a niekoniecznie tego potrzebujesz to tego nie rób :)
Z tego:

Obiekty maja bewne pole typu boolean. Ale to pole, moze byc TRUE tylko dla jednego obiektu w danej grupie. W tej sytuacji, robiac update na tym obiekcie i wstaiwajac to pole na TRUE, pozostale elementy musze ustawic na FALSE i wszystkie je zwrocic i przemapowac. usunac z listy poprzednie a nowe wlozyc..

wnioskuję, że albo dane nie do końca (lub też wcale) wpasowują się w model relacyjny albo coś jest nie tak z normalizacją modelu.
Może warto byłoby rozważyć inny sposób zapewnienia spójności i trwałości, nie znam problemu więc mogę tylko gdybać: może jakaś baza grafowa albo dokumentowa?

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