Asynchroniczne zapytania do bazy przy użyciu JPA

Asynchroniczne zapytania do bazy przy użyciu JPA
Nerkowiec
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 3 lata
  • Lokalizacja:Warszawa
  • Postów:8
0

Cześć,
Mam wystawiony endpoint, który używa kilku różnych widoków z kilku tabel, skleja to wszystko do kupy i zwraca użytkownikowi. ( korzystam z jparepository i encje widokowe )
Problem w tym, że chwilę to trwa, bo działa to synchronicznie, czyli select po selecie - i teraz potrzebuję zrobić to asynchronicznie, tak żeby te widoki nie czekały na siebie nawzajem tylko wszystkie odpalały się równolegle ( są od siebie niezależne )
Prosiłbym o wskazówki jak mogę to zaimplementować.

W0
  • Rejestracja:ponad 12 lat
  • Ostatnio:około godziny
  • Postów:3612
0

A w czym problem?
Większość frameworków ma jakiś mechanizm do zapytań asynchronicznych. Co więcej, jest jeszcze ExecutorService i Executors

Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
3

Najprościej pewnie jakimś CompletableFuture.supplyAsync(), chociaż ja bym się zastanowił czy nie da się tego zrobić za pomocą jednego query? Weź też pod uwagę potencjalne problemy z transakcjami/widocznością jeśli pójdziesz w kierunku wykonywania asychronicznych operacji.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 1x, ostatnio: Shalom
Koziołek
Moderator
  • Rejestracja:około 18 lat
  • Ostatnio:4 dni
  • Lokalizacja:Stacktrace
  • Postów:6822
0

@Nerkowiec: prosta odpowiedź w przypadku czystego JPA – nie da się. Po prostu działa ono z JDBC pod spodem, a to jest synchroniczne. Co możesz zrobić? Opakować wywołanie za pomocą jakiegoś frameworka reaktywnego. Masz już jak widzę Springa, więc możesz spróbować pobawić się reactive-spring, ale nadal mogą być problemy.

Proponuję trochę inne podejście. Napisz zapytanie, które będzie projekcją danych. Jedno zapytanie SQL, które zwróci wszystko, co potrzebujesz. Tak, to może być trudne, ale w następnym kroku opakuj je w R2DBC, czyli reaktywny sterownik baz danych, który zwróci ci odpowiedni kontener (Fulxa/Mono w przypadku Springa). Następnie będziesz musiał samodzielnie mapować rezultaty na coś obiekty albo po prostu wypchnąć jest do GUI i niech tam już je obrabiają, jak chcą.

ps. obczaj https://spring.io/projects/spring-data-r2dbc


Sięgam tam, gdzie wzrok nie sięga… a tam NullPointerException
edytowany 1x, ostatnio: Koziołek
PI
Brzmi typowo jak super rzeczy na konferencji, ale jednak zostanę przy swoim, jak najprostszym rozwiązaniu problemu :D
Koziołek
@Pinek: to się da podpiąć w kilkanaście minut, bo r2dbc ma wsparcie w springu » https://spring.io/projects/spring-data-r2dbc dorzucasz zależność do poma, dopisujesz konfigurację z adresem bazy danych dla sterownika i tyle.
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:około godziny
  • Postów:1881
0

@Koziołek: nie rozumiem, czego się nie da? Możesz opakować zapytania w promisy (poprzez CompletableFuture, RxJavy, Reactory itp) i w ten sposób zrównoleglić zapytania (zakładając, że nie będzie wzajemnego lockowania na poziomie bazy). Minus jest oczywiście taki, że trzeba dalej działać na zdetachowanych encjach, bo sesja jest thread-scoped (wiec lepiej już taki case ogarnąć żywym SQL).

Anyways +1 dla pomysłu z projekcją, czyli zrobienie tych selectów wcześniej, jeśli się da.


”Engineering is easy. People are hard.” Bill Coughran
edytowany 3x, ostatnio: Charles_Ray
Zobacz pozostały 1 komentarz
Charles_Ray
Autor pisze, że robi sekwencje N zapytań i chce je zrownoleglic ;) zrownoleglić można w zasadzie wszystko - strzały do API, odpytanie bazy itd. Kwestia nazewnictwa, które często jest stosowane zamiennie - asynchroniczne, rownolegle, nieblokujące, reaktywne, … Jednak clue widzę w zrownolegleniu właśnie
SO
Tylko nieblokujące i asynchroniczne =/= równoległe. Mogę mieć asynchroniczne, które nie jest równoległe. I równoległe, które nie jest asynchroniczne.
Charles_Ray
Potwierdzam, to nie jest to samo ;)
SO
A dobra, źle zrozumiałem Twój poprzedni komentarz ;) Z postu autora rzeczywiście tak jak napisałeś wynika, że tutaj chodzi o zrównoleglenie. A Koziolek chyba bardziej pisał o asynchroniczności.
Charles_Ray
Koziołek pisze o async non-blocking
Koziołek
Moderator
  • Rejestracja:około 18 lat
  • Ostatnio:4 dni
  • Lokalizacja:Stacktrace
  • Postów:6822
1

@Charles_Ray: no nie do końca to się uda. Różnica pomiędzy R2DBC, a opakowaniem leży w sposobie, w jaki używane są wątki połączeń. W R2DBC wątek oczekujący na dane z bazy będzie zwalniany i będzie mógł np. przetwarzać przychodzące dane. W przypadku opakowania nadal masz blokowany wątek połączenia, a zwalniany jest jedynie ten z puli Rx/Reactora czy co tam, używasz. Zatem zrównoleglenie w przypadku opakowania nadal jest ograniczone do liczby wątków JDBC, a w przypadku R2DBC do liczby połączeń, jakie może przyjąć baza.

Nam udało się dobić do 10k połączeń w Postgresie 13, ale po stronie Javy nie chciało to działać aż tak dobrze.

ps.


Sięgam tam, gdzie wzrok nie sięga… a tam NullPointerException
edytowany 1x, ostatnio: Koziołek
Charles_Ray
Jasne, nie twierdzę, że nie ma żadnych bottlenecków, ale da się coś wykminić bez wchodzenia w r2dbc :) bez wsparcia na niższym poziomie (sterownik, serwer, OS) zawsze trzeba będzie się ratować jakąś osobną pulą wątków itd

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.