sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur uppdaterar man JPA-enheter när backend-databasen ändras asynkront?

Jag rekommenderar att du lägger till en @Startup @Singleton klass som upprättar en JDBC-anslutning till PostgreSQL-databasen och använder LISTEN och NOTIFY för att hantera cache-ogiltigförklaring.

Uppdatera :Här är ett annat intressant sätt att använda pgq och en samling arbetare för ogiltigförklaring.

Ogiltighetssignalering

Lägg till en trigger på tabellen som uppdateras som skickar en NOTIFY närhelst en enhet uppdateras. På PostgreSQL 9.0 och över denna NOTIFY kan innehålla en nyttolast, vanligtvis ett rad-ID, så att du inte behöver ogiltigförklara hela din cache, bara entiteten som har ändrats. På äldre versioner där en nyttolast inte stöds kan du antingen lägga till de ogiltiga posterna till en tidsstämplad loggtabell som din hjälparklass frågar när den får en NOTIFY , eller bara ogiltigförklara hela cachen.

Din hjälpklass LISTEN nu s på NOTIFY händelser som utlösaren skickar. När den får en NOTIFY händelse, kan den ogiltigförklara enskilda cache-poster (se nedan), eller tömma hela cachen. Du kan lyssna efter notiser från databasen med PgJDBC:s lyssna/notifiera support. Du måste ta bort alla anslutningspooler som hanteras java.sql.Connection för att komma till den underliggande PostgreSQL-implementeringen så att du kan casta den till org.postgresql.PGConnection och ring getNotifications() på den.

Ett alternativ till LISTEN och NOTIFY , du kan polla en ändringsloggtabell på en timer och låta en trigger i problemtabellen lägga till ändrade rad-ID och ändra tidsstämplar till ändringsloggtabellen. Detta tillvägagångssätt kommer att vara portabelt förutom behovet av en annan utlösare för varje DB-typ, men det är ineffektivt och mindre aktuellt. Det kommer att kräva frekvent ineffektiv polling och fortfarande ha en tidsfördröjning som lyssnings-/notifieringsmetoden inte gör. I PostgreSQL kan du använda en UNLOGGED tabell för att minska kostnaderna för detta tillvägagångssätt lite.

Cachenivåer

EclipseLink/JPA har ett par nivåer av caching.

Den första nivåns cache finns i EntityManager nivå. Om en enhet är kopplad till en EntityManager av persist(...) , merge(...) , find(...) , etc, sedan EntityManager krävs för att returnera samma instans av den entiteten när den nås igen inom samma session, oavsett om din applikation fortfarande har referenser till den eller inte. Den här bifogade instansen kommer inte att vara uppdaterad om ditt databasinnehåll sedan dess har ändrats.

Den andra nivåns cache, som är valfri, finns på EntityManagerFactory nivå och är en mer traditionell cache. Det är inte klart om du har 2:a nivåns cache aktiverat. Kontrollera dina EclipseLink-loggar och din persistence.xml . Du kan få tillgång till den andra nivåns cache med EntityManagerFactory.getCache(); se Cache .

@thedayofcondor visade hur man spolar 2:a nivåns cache med:

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

men du kan också vräka enskilda objekt med evict(java.lang.Class cls, java.lang.Object primaryKey) ring:

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

som du kan använda från din @Startup @Singleton NOTIFY lyssnaren för att ogiltigförklara endast de poster som har ändrats.

Den första nivåns cache är inte så lätt, eftersom det är en del av din applikationslogik. Du kommer att vilja lära dig hur EntityManager , bifogade och fristående enheter, etc. arbete. Ett alternativ är att alltid använda fristående entiteter för tabellen i fråga, där du använder en ny EntityManager närhelst du hämtar enheten. Denna fråga:

Ogiltigförklarar JPA EntityManager-session

har en användbar diskussion om att hantera ogiltigförklaring av enhetshanterarens cache. Det är dock osannolikt att en EntityManager cachen är ditt problem, eftersom en RESTful webbtjänst vanligtvis implementeras med kort EntityManager sessioner. Detta är sannolikt bara ett problem om du använder utökade persistenskontexter eller om du skapar och hanterar din egen EntityManager sessioner istället för att använda behållarhanterad persistens.



  1. Hur flyttar jag en tabell till ett schema i T-SQL

  2. Hur RIGHT()-funktionen fungerar i MySQL

  3. Hur använder man MySQLdb med Python och Django i OSX 10.6?

  4. Oracle:Finns det något sätt att få nya SQL-syntaxfel?