Kacper Zieliński

Kacper Zieliński Student, Akademia
Górniczo-Hutnicza
im. Stanisława
Staszi...

Temat: JPA + Aplikacja Desktopowa - przechowywanie dużej ilości...

Witam,

Mam pytanie związane z projektem, który aktualnie tworzę. W skrócie: system (aplikacja desktopowa), który pobiera/zapisuje dane z bazy(MySQL) przy użyciu JPA.
Aktualnie wczytuje wszystkie dane i przechowuje w pamięci w postaci lisy (dlaczego? - wydawało mi się to elastyczne), oraz wyświetlam w JTable. Wszystko działa, jednak (jak można było się domyśleć) podejście takie zawodzi przy dużej ilości danych w bazie (ponad 50 tys rekordów) - przepełnia się stos.

Moje pytanie: W jaki sposób przechowywać i odwoływać się do danych w takiej aplikacji? Aktualnie po głowie chodzi mi pomysł, żeby wczytywać dane seriami (powiedzmy po 1000 rekordów)podczas uruchamiania, i wstawiać do tabeli (id, nazwa, itd) - bez przechowywania całych encji. Następnie w sytuacji, gdy dane z któregoś rekordu będą potrzebne, odczytać ID z tabeli i pobrać z bazy (entityManager.find(..)). Czy jest to dobre rozwiązanie, czy może ktoś poleci inne?

z góry dziękuję za pomoc.
Roger Zacharczyk

Roger Zacharczyk Programista (gry,
webserwisy,
aplikacje użytkowe),
fotograf

Temat: JPA + Aplikacja Desktopowa - przechowywanie dużej ilości...

w SQL jest parametr LIMIT który określa od którego do którego wiersza chcemy pobrać dane. Poszukaj czegoś pod tym kątem w JPA.

Edit:
coś takiego by było...
query.setFirstResult(firstPosition);
query.setMaxResults(numberOfRecords);
Ale w tej chwili nie powiem, czy to zadziała. Tak na szybko znalazłem wiedząc o LIMIT.Roger Zacharczyk edytował(a) ten post dnia 30.07.10 o godzinie 15:08
Kacper Zieliński

Kacper Zieliński Student, Akademia
Górniczo-Hutnicza
im. Stanisława
Staszi...

Temat: JPA + Aplikacja Desktopowa - przechowywanie dużej ilości...

Roger Zacharczyk:
w SQL jest parametr LIMIT który określa od którego do którego wiersza chcemy pobrać dane. Poszukaj czegoś pod tym kątem w JPA.

Edit:
coś takiego by było...
query.setFirstResult(firstPosition);
query.setMaxResults(numberOfRecords);
Ale w tej chwili nie powiem, czy to zadziała. Tak na szybko znalazłem wiedząc o LIMIT.


Dokładnie tak chce teraz zrobić. Dodam, ze w tabeli muszę wyświetlić zawartość całej bazy.
Ten sposób działa (po części już go zaimplementowałem), i z pewnością lepiej od poprzedniego, jednak czy jest to dobry sposób, wystarczający, czy może jest jakiś lepszy??Kacper Zet edytował(a) ten post dnia 24.08.10 o godzinie 12:31
Roger Zacharczyk

Roger Zacharczyk Programista (gry,
webserwisy,
aplikacje użytkowe),
fotograf

Temat: JPA + Aplikacja Desktopowa - przechowywanie dużej ilości...

Kacper Zieliński:
Dokładnie tak chce teraz zrobić. Dodam, ze w tabeli muszę wyświetlić zawartość całej bazy.
Ten sposób działa (po części już go zaimplementowałem), i z pewnością lepiej od poprzedniego, jednak czy jest to dobry sposób, wystarczający, czy może jest jakiś lepszy??Kacper Zieliński edytował(a) ten post dnia 30.07.10 o godzinie 15:22
Sądzę, że jest to jedyny sposób na wyciąganie rekordów "partiami" przy pomocy JPA. Chyba, że chcesz bawić się w czytanie ID, na którym skończyłeś, ale to raczej uderzy po wydajności i roboczogodzinach. ;)
Trzymałbym się więc tego rozwiązania.
Kacper Zieliński

Kacper Zieliński Student, Akademia
Górniczo-Hutnicza
im. Stanisława
Staszi...

Temat: JPA + Aplikacja Desktopowa - przechowywanie dużej ilości...

Dzięki Roger - w takim razie do dzieła!:) Jednak jeśli ktoś zna jakiś inny sposób (niekoniecznie ze stronicowaniem) to również proszę o informacje - może przyda sie na przyszłość mi lub komuś innemu.
pozdrawiam.
Adrian C.

Adrian C.
projektant/programis
ta

Temat: JPA + Aplikacja Desktopowa - przechowywanie dużej ilości...

Nie wiem jak bardzo zależy Ci na wydajności, ale pamiętaj że używanie w mySQL offset i limit jest bardzo nie wydajne. Limit sam w sobie jest ok, ale offset przy dużej ilości danych może stać się kłopotliwy.

Temat: JPA + Aplikacja Desktopowa - przechowywanie dużej ilości...

nie może się stać a będzie kłopotliwy ;)

http://www.scribd.com/doc/14683263/Efficient-Paginatio...

podobną strategie opisywali na facebooku ale nie mogę znaleźć linka teraz.
Jeśli faktycznie ilość danych jest duża to warto się nad tym zastanowić.
Kacper Zieliński

Kacper Zieliński Student, Akademia
Górniczo-Hutnicza
im. Stanisława
Staszi...

Temat: JPA + Aplikacja Desktopowa - przechowywanie dużej ilości...

Ok, o ile z wczytaniem poszło gładko, o tyle pojawił się problem z przechowywaniem danych w JTable. Podczas wczytywania dane wczytuję do DefaultTableModel, po zakończeniu tworzę JTable na podstawie tego modelu.

Problem jest z "kopią zapasową". Na tabeli będą przeprowadzane różne operacje, które "majstrują" przy modelu.

Wydaje mi się, że najlepszym wyjściem jest stworzenie jednego modelu, którego zawartość jest stała, a do tabel ładować jego kopie. Tylko niestety DTM nie ma konstruktora kopiującego, ani żadnej metody którą można użyć.
I teraz pytanie - czy jedynym wyjściem jest napisanie metody opartej na pętli for i przepisanie zawartości modelu (co wydaje mi sie nieefektywne;/)? Kombinowałem z getDataVector(), ale tez coś nie poszło.

Czy może ktoś ma lepszy sposób. Dodam, że szukałem już w googlach, ale nic interesującego nie znalazłem.
Może w ogóle pomysł z przechowywaniem danych w modelu jest kiepski?Kacper Zet edytował(a) ten post dnia 09.08.10 o godzinie 13:32

konto usunięte

Temat: JPA + Aplikacja Desktopowa - przechowywanie dużej ilości...

Pomysł z przechowywaniem danych w modelu jest ok, ale zrezygnuj z domyślnego modelu (DefaultTableModel). Zdecyduj się lepiej na implementację interfejsu TableModel - to da Ci większą elastyczność i płynną modyfikację przechowywanych danych. Interfejs ten ma raptem kilka metod do implementacji, których zrozumienie nie sprawi Ci problemu (wszystkie występują w DefaultTableModel). Jedynie metodę do dodawania danych od strony aplikacji (nie bazy danych) musisz stworzyć w całości (łącznie z prototypem).

Powodzenia
Adrian C.

Adrian C.
projektant/programis
ta

Temat: JPA + Aplikacja Desktopowa - przechowywanie dużej ilości...

Nie wiem jak bardzo skomplikowany masz model, ale może rozwiązaniem byłoby pamiętanie zmian robionych przez użytkownika. Odkładaj sobie je gdzieś na boku, jeśli użytkownik potwierdzi zmiany to robisz aktualizację w bazie i zapominasz o tych zmianach, jeśli będzie chciał cofnąć to w wykonanie w odwrotnej kolejności zmian pozwoli Ci na powrócenie do stanu pierwotnego. Takie podejście ma tez swoje zalety w momencie zapisu do bazy, nie musisz synchronizować całej kolekcji, ale tylko te obiekty, z którymi związane są zmiany.

konto usunięte

Temat: JPA + Aplikacja Desktopowa - przechowywanie dużej ilości...

Witam miałem do rozwiązania podobny problem, założenia były następujące:
-50 000~150 000 encji
-Prezentacja pełnej listy w tabeli
-Świeżość encji (równoległa praca na danych wielu instancji oprogramowania)
-Eclipse RCP, Hibernate, MySQL
Wnioski
-Na "golasa" po JDBC dowiedziałem się że można zapomnieć o wsparciu w przemieszczaniu się góra dół kursorem (metody są lecz ich implementacja w JDBC tak czy owak pobiera całość danych i przetwarza je lokalnie), wsparcie tylko dla operacji *.first...while(*.HasNext())...*.Next()... jakoś tak.
-Hibernate bazuje na JDBC więc rewelacji w temacie brak.
Rozwiązanie
-Dynamiczny (własny) model tabeli, gdzie jako count podajesz właściwą liczbę wierszy (aby scroll był poprawnie skalowany) a dane stronnicujesz dynamicznie (zawsze wiesz jaki ID jest proszony przeliczysz go an pozycję w ArrayList, jeżeli wynika że jest poza pobierasz kolejną (WHERE id BETWEEN ${currentId - interval} and ${currentID + arraySize} porcję kasując poprzednią)
-Optymalizacja: dobrze dopasuj bufor aby przeładowanie nie było zbyt częste, lub trwało zbyt długo. Korzystaj z puli połączeń. Zbuduj tak aplikację by użytkownik chętniej zawężał listę (WHERE) niż przeglądał ją całą

Pozdrawiam
Mateusz Jancy
Kacper Zieliński

Kacper Zieliński Student, Akademia
Górniczo-Hutnicza
im. Stanisława
Staszi...

Temat: JPA + Aplikacja Desktopowa - przechowywanie dużej ilości...

Dzięki wielkie za odpowiedzi.

Ostatecznie rozszerzyłem klase DefaultTableModel, dodając potrzebne mi metody i w niej przechowuję dane. Puki co działa dla 40 000 danych - co dla mnie jest wystarczające:)
Moje spostrzeżenie dla potomnych (może oczywiste, ale co tam):
Nie pobierajcie całych encji przy większej ilości danych (Select p from person p) o ile nie są wymagane wszystkie dane. Najlepiej wyciągnąć najbardziej potrzebne dane do List<Object[]> getResultList'em i potem ewentualnie pobierać pojedyncze encje na podstawie klucza.

Oczywiście należy wykorzystać stronicowanie, i trochę pokombinować.

Jeszcze raz dzięki wszystkim za pomocKacper Zet edytował(a) ten post dnia 24.08.10 o godzinie 12:39

Następna dyskusja:

Duże ilości danych / porada




Wyślij zaproszenie do