后端数据库异步更改时如何刷新JPA实体?

后端数据库异步更改时如何刷新JPA实体?,第1张

后端数据库异步更改时如何刷新JPA实体

我建议添加一个

@Startup

@Singleton
类,该类建立与PostgreSQL数据库的JDBC连接,并使用
LISTEN
NOTIFY
处理高速缓存失效。

更新
:这是另一种有趣的方法,使用pgq和一组worker进行失效。

无效信令

在要更新的表上添加一个触发器,该触发器在

NOTIFY
实体更新时发送一个。在PostgreSQL
9.0及更高版本上,它
NOTIFY
可以包含有效负载,通常是行ID,因此您不必使整个缓存无效,而只需使已更改的实体无效。在不支持有效负载的旧版本中,您可以将无效的条目添加到带有时间戳的日志表中,当您的帮助程序类获得时,该日志表将向其查询
NOTIFY
,或者仅使整个缓存无效。

现在,您的帮助程序类

LISTEN
基于
NOTIFY
触发器发送的事件。收到
NOTIFY
事件后,它可使单个缓存条目无效(请参见下文),或刷新整个缓存。您可以使用PgJDBC的监听/通知支持来监听来自数据库的通知。您将需要解开所有管理
java.sql.Connection
到底层PostgreSQL实现的连接池,以便可以将其强制转换
org.postgresql.PGConnection
并调用
getNotifications()
它。

一种替代

LISTEN
NOTIFY
,你可以轮询计时器的更改日志表,以及对问题表追加改变行ID和变化时间戳来更改日志表的触发器。这种方法将是可移植的,除了每种DB类型都需要不同的触发器外,这种方法效率低下且不及时。这将需要频繁的低效轮询,并且仍然存在侦听/通知方法不需要的时间延迟。在PostgreSQL中,您可以使用
UNLOGGED
表来减少这种方法的成本。

缓存级别

Eclipselink / JPA有几个缓存级别。

第一级缓存处于该

EntityManager
级别。如果实体附加到
EntityManager
通过
persist(...)
merge(...)
find(...)
,等,则
EntityManager
需要返回_该实体的同一实例_ 时,它是在同一会话内再次访问,不管是不是你的应用程序仍然有它的引用。如果您的数据库内容此后发生更改,则此附加实例将不是最新的。

第二级高速缓存(是可选的)处于该

EntityManagerFactory
级别,并且是更传统的高速缓存。尚不清楚是否启用了二级缓存。检查您的Eclipselink日志和您的
persistence.xml
。您可以使用
EntityManagerFactory.getCache()
;
访问第二级缓存。见
Cache

@thedayofcondor显示了如何使用以下方法刷新第二级缓存:

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

但您也可以通过

evict(java.lang.Class cls, java.lang.ObjectprimaryKey)
调用将单个对象逐出:

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

您可以从

@Startup
@Singleton
NOTIFY
侦听器使用它来仅使那些已更改的条目无效。

1级缓存并不是那么容易,因为它是应用程序逻辑的一部分。您将要了解

EntityManager
,附加和分离的实体等的工作方式。一种选择是始终对表使用分离的实体,在
EntityManager
获取实体时在其中使用新的实体。

对处理实体管理器的缓存无效进行了有益的讨论。但是,

EntityManager
缓存不太可能是您的问题,因为RESTful
Web服务通常使用短
EntityManager
会话来实现。仅当您使用扩展的持久性上下文,或者正在创建和管理自己的
EntityManager
会话而不是使用容器管理的持久性时,才可能出现问题。



欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5586599.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-14
下一篇2022-12-14

发表评论

登录后才能评论

评论列表(0条)

    保存