Doporučuji přidat @Startup
@Singleton
třída, která naváže připojení JDBC k databázi PostgreSQL a používá LISTEN
a NOTIFY
ke zpracování neplatnosti mezipaměti.
Aktualizovat :Zde je další zajímavý přístup, pomocí pgq a kolekce pracovníků pro zneplatnění.
Signalizace zneplatnění
Přidejte na tabulku, která se aktualizuje, spouštěč, který odešle NOTIFY
kdykoli je entita aktualizována. Na PostgreSQL 9.0 a vyšší toto NOTIFY
může obsahovat užitečné zatížení, obvykle ID řádku, takže nemusíte zneplatnit celou mezipaměť, pouze entitu, která se změnila. Ve starších verzích, kde není užitečné zatížení podporováno, můžete buď přidat neplatné položky do tabulky protokolu s časovým razítkem, kterou se vaše pomocná třída dotazuje, když dostane NOTIFY
nebo rovnou zneplatnit celou mezipaměť.
Vaše pomocná třída nyní LISTEN
s na NOTIFY
události, které trigger odešle. Když dostane NOTIFY
může zneplatnit jednotlivé položky cache (viz níže) nebo vyprázdnit celou cache. Můžete poslouchat oznámení z databáze s podporou naslouchání/upozorňování PgJDBC. Budete muset rozbalit jakýkoli fond připojení spravovaný java.sql.Connection
abyste se dostali k základní implementaci PostgreSQL, abyste ji mohli přenést do org.postgresql.PGConnection
a zavolejte getNotifications()
na to.
Alternativa k LISTEN
a NOTIFY
, můžete dotazovat tabulku protokolu změn na časovači a mít spouštěč v tabulce problémů připojovat změněná ID řádků a měnit časová razítka do tabulky protokolu změn. Tento přístup bude přenosný s výjimkou potřeby jiného spouštěče pro každý typ DB, ale je neefektivní a méně aktuální. Bude to vyžadovat časté neefektivní dotazování a stále bude mít časové zpoždění, které přístup naslouchání/upozorňování nezaznamená. V PostgreSQL můžete použít UNLOGGED
tabulky, aby se trochu snížily náklady na tento přístup.
Úrovně mezipaměti
EclipseLink/JPA má několik úrovní ukládání do mezipaměti.
Mezipaměť 1. úrovně je v EntityManager
úroveň. Pokud je entita připojena k EntityManager
od persist(...)
, merge(...)
, find(...)
, atd., pak EntityManager
je nutné vrátit stejnou instanci této entity při opětovném přístupu v rámci stejné relace, bez ohledu na to, zda na něj vaše aplikace stále odkazuje. Tato připojená instance nebude aktuální, pokud se obsah vaší databáze mezitím změnil.
Mezipaměť 2. úrovně, která je volitelná, se nachází v EntityManagerFactory
úroveň a je tradičnější cache. Není jasné, zda máte povolenou mezipaměť 2. úrovně. Zkontrolujte své protokoly EclipseLink a persistence.xml
. Přístup k mezipaměti 2. úrovně můžete získat pomocí EntityManagerFactory.getCache()
; viz Cache
.
@thedayofcondor ukázal, jak vyprázdnit mezipaměť 2. úrovně pomocí:
em.getEntityManagerFactory().getCache().evictAll();
ale můžete také vystěhovat jednotlivé objekty pomocí evict(java.lang.Class cls, java.lang.Object primaryKey)
zavolejte:
em.getEntityManagerFactory().getCache().evict(theClass, thePrimaryKey);
který můžete použít ze svého @Startup
@Singleton
NOTIFY
listener zrušit platnost pouze těch položek, které se změnily.
Mezipaměť 1. úrovně není tak snadná, protože je součástí vaší aplikační logiky. Budete chtít zjistit, jak funguje EntityManager
, připojené a oddělené entity atd. Jednou z možností je vždy použít oddělené entity pro danou tabulku, kde použijete nový EntityManager
kdykoli získáte entitu. Tato otázka:
Zrušení relace EntityManager JPA
má užitečnou diskuzi o manipulaci se zneplatněním mezipaměti správce entity. Je však nepravděpodobné, že by šlo o EntityManager
cache je váš problém, protože webová služba RESTful je obvykle implementována pomocí krátkého EntityManager
sezení. To bude pravděpodobně problém pouze v případě, že používáte kontexty rozšířené perzistence nebo pokud vytváříte a spravujete svůj vlastní EntityManager
relací namísto použití persistence spravované kontejnerem.