Asynchroniczne zapytania do bazy przy użyciu JPA

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ć.

0

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

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.

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

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.

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.

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