PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Jak odświeżyć encje JPA, gdy baza danych zaplecza zmienia się asynchronicznie?

Polecam dodanie @Startup @Singleton klasa, która nawiązuje połączenie JDBC z bazą danych PostgreSQL i używa LISTEN i NOTIFY do obsługi unieważniania pamięci podręcznej.

Aktualizacja :Oto kolejne interesujące podejście, wykorzystujące pgq i zbiór pracowników do unieważniania.

Sygnalizacja unieważnienia

Dodaj wyzwalacz do aktualizowanej tabeli, który wysyła komunikat NOTIFY za każdym razem, gdy jednostka jest aktualizowana. W PostgreSQL 9.0 i nowszych to NOTIFY może zawierać ładunek, zwykle identyfikator wiersza, więc nie musisz unieważniać całej pamięci podręcznej, tylko zmienioną encję. W starszych wersjach, w których ładunek nie jest obsługiwany, można dodać unieważnione wpisy do tabeli dziennika ze znacznikiem czasu, do której odpytuje klasa pomocnicza, gdy otrzyma komunikat NOTIFY lub po prostu unieważnij całą pamięć podręczną.

Twoja klasa pomocnicza teraz LISTEN s na NOTIFY zdarzenia wysyłane przez wyzwalacz. Gdy otrzyma NOTIFY zdarzenia, może unieważnić pojedyncze wpisy w pamięci podręcznej (patrz poniżej) lub opróżnić całą pamięć podręczną. Możesz nasłuchiwać powiadomień z bazy danych dzięki obsłudze nasłuchu/powiadomienia PgJDBC. Będziesz musiał rozpakować wszystkie zarządzane przez pulę połączeń java.sql.Connection aby uzyskać dostęp do podstawowej implementacji PostgreSQL, aby można było przesłać ją do org.postgresql.PGConnection i wywołaj getNotifications() na nim.

Alternatywa dla LISTEN i NOTIFY , można odpytywać tabelę dziennika zmian na czasomierzu, a wyzwalacz w tabeli problemów dołącza zmienione identyfikatory wierszy i znaczniki czasu zmian do tabeli dziennika zmian. To podejście będzie przenośne, z wyjątkiem potrzeby innego wyzwalacza dla każdego typu bazy danych, ale jest nieefektywne i mniej terminowe. Będzie to wymagało częstego, nieefektywnego odpytywania i nadal będzie miało opóźnienie, którego nie ma podejście słuchania/powiadamiania. W PostgreSQL możesz użyć UNLOGGED tabeli, aby nieco obniżyć koszty tego podejścia.

Poziomy pamięci podręcznej

EclipseLink/JPA ma kilka poziomów buforowania.

Pamięć podręczna pierwszego poziomu znajduje się w EntityManager poziom. Jeśli encja jest dołączona do EntityManager przez persist(...) , merge(...) , find(...) itd., a następnie EntityManager jest zobowiązany do zwrócenia tego samego wystąpienia tego podmiotu gdy jest ponownie dostępny w tej samej sesji, niezależnie od tego, czy aplikacja nadal ma do niej odniesienia. Ta podłączona instancja nie będzie aktualna, jeśli zawartość Twojej bazy danych uległa zmianie.

Pamięć podręczna drugiego poziomu, która jest opcjonalna, znajduje się w EntityManagerFactory poziomie i jest bardziej tradycyjną pamięcią podręczną. Nie jest jasne, czy masz włączoną pamięć podręczną drugiego poziomu. Sprawdź swoje dzienniki EclipseLink i plik persistence.xml . Możesz uzyskać dostęp do pamięci podręcznej drugiego poziomu za pomocą EntityManagerFactory.getCache(); zobacz Cache .

@thedayofcondor pokazał, jak opróżnić pamięć podręczną drugiego poziomu za pomocą:

em.getEntityManagerFactory().getCache().evictAll();

ale możesz także eksmitować poszczególne obiekty za pomocą evict(java.lang.Class cls, java.lang.Object primaryKey) zadzwoń:

em.getEntityManagerFactory().getCache().evict(theClass, thePrimaryKey);

którego możesz użyć ze swojego @Startup @Singleton NOTIFY listener, aby unieważnić tylko te wpisy, które uległy zmianie.

Pamięć podręczna pierwszego poziomu nie jest taka prosta, ponieważ jest częścią logiki aplikacji. Będziesz chciał dowiedzieć się, jak EntityManager , dołączone i odłączone jednostki itp. Jedną z opcji jest zawsze używanie odłączonych encji dla danej tabeli, gdzie używasz nowego EntityManager za każdym razem, gdy pobierasz jednostkę. To pytanie:

Unieważnianie sesji JPA EntityManager

zawiera przydatne omówienie obsługi unieważniania pamięci podręcznej menedżera encji. Jednak jest mało prawdopodobne, aby EntityManager cache to Twój problem, ponieważ usługa sieciowa RESTful jest zwykle implementowana przy użyciu krótkiego EntityManager sesje. Jest to prawdopodobnie problem tylko wtedy, gdy używasz rozszerzonych kontekstów trwałości lub jeśli tworzysz i zarządzasz własnym EntityManager sesji zamiast używania trwałości zarządzanej przez kontener.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Programowo wyprodukuj obiekt `DataSource` dla Postgres JDBC

  2. Tworzenie nowych modułów za pomocą rozszerzenia PostgreSQL Create

  3. PostgreSQL:jaki typ danych powinien być używany dla waluty?

  4. Scalanie konkatenacji kolumn JSON(B) w zapytaniu

  5. Utwórz tabelę dwóch typów w PostgreSQL