sql >> Database >  >> RDS >> PostgreSQL

Hoe JPA-entiteiten vernieuwen wanneer de backend-database asynchroon verandert?

Ik raad aan om een ​​@Startup . toe te voegen @Singleton klasse die een JDBC-verbinding tot stand brengt met de PostgreSQL-database en gebruikmaakt van LISTEN en NOTIFY om cache-invalidatie af te handelen.

Bijwerken :Hier is nog een interessante benadering, met behulp van pgq en een verzameling werkers voor ongeldigverklaring.

Ongeldige signalering

Voeg een trigger toe aan de tabel die wordt bijgewerkt en die een NOTIFY . verzendt telkens wanneer een entiteit wordt bijgewerkt. Op PostgreSQL 9.0 en hoger deze NOTIFY kan een payload bevatten, meestal een rij-ID, dus u hoeft niet uw hele cache ongeldig te maken, alleen de entiteit die is gewijzigd. Op oudere versies waar een payload niet wordt ondersteund, kunt u de ongeldige vermeldingen toevoegen aan een logboektabel met tijdstempel die uw helperklasse opvraagt ​​​​wanneer deze een NOTIFY krijgt , of maak gewoon de hele cache ongeldig.

Je hulpklas nu LISTEN s op de NOTIFY gebeurtenissen die de trigger verzendt. Wanneer het een NOTIFY . krijgt gebeurtenis, kan het individuele cache-items ongeldig maken (zie hieronder), of de hele cache leegmaken. U kunt luisteren naar meldingen uit de database met PgJDBC's luister-/meldingsondersteuning. U moet elke door verbindingspooler beheerde java.sql.Connection . uitpakken om bij de onderliggende PostgreSQL-implementatie te komen, zodat u deze kunt casten naar org.postgresql.PGConnection en bel getNotifications() erop.

Een alternatief voor LISTEN en NOTIFY , u kunt een wijzigingslogboektabel op een timer pollen en een trigger op de probleemtabel laten wijzigen rij-ID's en tijdstempels wijzigen in de wijzigingslogboektabel. Deze aanpak is draagbaar, behalve dat er voor elk DB-type een andere trigger nodig is, maar is inefficiënt en minder actueel. Het vereist frequente inefficiënte polling en heeft nog steeds een vertraging die de luister-/meldingsbenadering niet heeft. In PostgreSQL kunt u een UNLOGGED . gebruiken tabel om de kosten van deze aanpak een beetje te verlagen.

Cacheniveaus

EclipseLink/JPA heeft een aantal cachingniveaus.

De cache van het 1e niveau bevindt zich in de EntityManager peil. Als een entiteit is gekoppeld aan een EntityManager door persist(...) , merge(...) , find(...) , etc, dan de EntityManager is vereist om dezelfde instantie van die entiteit te retourneren wanneer het binnen dezelfde sessie opnieuw wordt geopend, ongeacht of uw toepassing er nog steeds naar verwijst. Dit bijgevoegde exemplaar is niet up-to-date als de inhoud van uw database sindsdien is gewijzigd.

De cache van het 2e niveau, die optioneel is, bevindt zich in de EntityManagerFactory level en is een meer traditionele cache. Het is niet duidelijk of u de cache van het 2e niveau hebt ingeschakeld. Controleer uw EclipseLink-logboeken en uw persistence.xml . U kunt toegang krijgen tot de cache van het 2e niveau met EntityManagerFactory.getCache(); zie Cache .

@thedayofcondor liet zien hoe je de cache van het 2e niveau leegmaakt met:

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

maar u kunt ook individuele objecten verwijderen met de evict(java.lang.Class cls, java.lang.Object primaryKey) bel:

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

die u kunt gebruiken vanaf uw @Startup @Singleton NOTIFY luisteraar om alleen die vermeldingen ongeldig te maken die zijn gewijzigd.

De cache van het eerste niveau is niet zo eenvoudig, omdat het deel uitmaakt van uw toepassingslogica. U wilt weten hoe de EntityManager , gekoppelde en vrijstaande entiteiten, enz. werken. Een optie is om voor de betreffende tabel altijd vrijstaande entiteiten te gebruiken, waarbij je een nieuwe EntityManager gebruikt. telkens wanneer u de entiteit ophaalt. Deze vraag:

JPA EntityManager-sessie ongeldig maken

heeft een nuttige bespreking van het afhandelen van ongeldigverklaring van de cache van de entiteitsmanager. Het is echter onwaarschijnlijk dat een EntityManager cache is jouw probleem, omdat een RESTful-webservice meestal wordt geïmplementeerd met behulp van de korte EntityManager sessies. Dit is waarschijnlijk alleen een probleem als u uitgebreide persistentiecontexten gebruikt of als u uw eigen EntityManager maakt en beheert. sessies in plaats van door containerbeheerde persistentie te gebruiken.



  1. Transformatie van rijen naar kolommen in Oracle

  2. Oracle Concatenate String- en nummervoorbeelden

  3. Vensterfuncties of algemene tabeluitdrukkingen:tel vorige rijen binnen bereik

  4. 3 manieren om de sortering van een kolom in MariaDB te krijgen