
我建议添加一个
@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会话而不是使用容器管理的持久性时,才可能出现问题。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)