PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Как да опресня JPA обекти, когато бекенд базата данни се промени асинхронно?

Препоръчвам да добавите @Startup @Singleton клас, който установява JDBC връзка към базата данни PostgreSQL и използва LISTEN и NOTIFY за обработка на невалидирането на кеша.

Актуализиране :Ето още един интересен подход, използващ pgq и колекция от работници за обезсилване.

Сигнализиране за невалидност

Добавете тригер към таблицата, която се актуализира, която изпраща NOTIFY всеки път, когато даден обект се актуализира. На PostgreSQL 9.0 и по-нова версия това NOTIFY може да съдържа полезен товар, обикновено идентификатор на ред, така че не е нужно да обезсилвате целия си кеш, а само обекта, който е променен. В по-стари версии, където полезен товар не се поддържа, можете или да добавите невалидните записи към таблица с времеви маркировки, която вашият помощен клас отправя към запитвания, когато получи NOTIFY , или просто анулирайте целия кеш.

Вашият помощен клас сега LISTEN s на NOTIFY събития, които тригерът изпраща. Когато получи NOTIFY събитие, може да анулира отделните записи в кеша (вижте по-долу) или да изчисти целия кеш. Можете да слушате за известия от базата данни с поддръжката за слушане/уведомяване на PgJDBC. Ще трябва да разгънете всеки пул за връзки, управляван java.sql.Connection за да стигнете до основната реализация на PostgreSQL, за да можете да я прехвърлите към org.postgresql.PGConnection и извикайте getNotifications() върху него.

Алтернатива на LISTEN и NOTIFY , бихте могли да анкетирате таблица с регистрационни файлове за промени на таймер и да накарате тригер към таблицата с проблеми да добави променени идентификатори на редове и да промени времеви печати към таблицата на регистрационния файл на промените. Този подход ще бъде преносим, ​​с изключение на необходимостта от различен тригер за всеки тип DB, но е неефективен и по-малко навременен. Това ще изисква често неефективно допитване и все пак ще има забавяне във времето, което подходът слушане/уведомяване няма. В PostgreSQL можете да използвате UNLOGGED таблица, за да намалите малко разходите за този подход.

Нива на кеша

EclipseLink/JPA има няколко нива на кеширане.

Кешът от 1-во ниво е в EntityManager ниво. Ако обект е прикачен към EntityManager от persist(...) , merge(...) , find(...) и т.н., след това EntityManager се изисква да върне същия екземпляр на този обект когато бъде достъпен отново в рамките на същата сесия, независимо дали приложението ви все още има препратки към него. Този прикачен екземпляр няма да е актуален, ако съдържанието на базата ви оттогава се е променило.

Кешът от 2-ро ниво, който не е задължителен, е в EntityManagerFactory ниво и е по-традиционен кеш. Не е ясно дали имате активиран кеш от 2-ро ниво. Проверете вашите регистрационни файлове на EclipseLink и вашия persistence.xml . Можете да получите достъп до кеша от 2-ро ниво с EntityManagerFactory.getCache(); вижте Cache .

@thedayofcondor показа как да прочистите кеша от 2-ро ниво с:

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

но можете също да изгоните отделни обекти с evict(java.lang.Class cls, java.lang.Object primaryKey) обадете се:

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

които можете да използвате от вашия @Startup @Singleton NOTIFY слушателят да анулира само онези записи, които са променени.

Кешът от 1-во ниво не е толкова лесен, защото е част от логиката на вашето приложение. Ще искате да научите как EntityManager , прикачени и обособени лица и др. Една от опциите е винаги да използвате обособени обекти за въпросната таблица, където използвате нов EntityManager всеки път, когато извлечете обекта. Този въпрос:

Невалидна сесия на JPA EntityManager

има полезна дискусия за обработка на невалидиране на кеша на мениджъра на обект. Малко вероятно е обаче EntityManager кешът е вашият проблем, тъй като уеб услугата RESTful обикновено се реализира с помощта на кратък EntityManager сесии. Това вероятно ще е проблем само ако използвате разширени контексти за постоянство или ако създавате и управлявате свой собствен EntityManager сесии, вместо да се използва постоянство, управлявано от контейнер.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Местоположение по подразбиране на базата данни PostgreSQL в Linux

  2. Как да ускоря броенето на редове в PostgreSQL таблица?

  3. Анотацията на Spring Boot Query с nativeQuery не работи в Postgresql

  4. Събитието ROLLBACK се задейства в postgresql

  5. [Видео] Ansible и PostgreSQL