相当于 Javax Cache 'put'插入或更新的 SQL

问题描述

我正在使用 javax 缓存数据库。我使用缓存的 API 来获取/放置/删除实体,并且数据库位于此缓存之后。为此,我使用了 CacheLoaderCacheWriter

所以,下面是等价于缓存 API 的 sql 构造

  1. 选择 -> 获取
  2. 插入 -> 放置
  3. 删除 -> 删除

如果我已经在缓存中存在条目并且我更新了它,那么我将仅获得该值“写入”方法。但是,由于该值存在于数据库中,因此我需要使用 UPDATE 查询

如何确定在缓存的“放置”操作中执行哪个数据库操作?

注意:性能的角度来看,UPSERT 不是一个好的选择。

解决方法

如果您将值放入缓存中,您可以先检查该键是否已经存在,在这种情况下您需要更新。如果密钥不存在,则需要插入。听起来您可以从带有 L2 缓存的 ORM 中受益,例如 Hibernate,它可以为您处理所有这些场景(以及更多场景)。

,

我可以想到几种方法。基本上这些是以下变体:

数据库中的元数据

在实体中,我通常有附加字段,它们是插入和更新的时间戳以及由对象处理到关系映射器 (ORM) 的修改计数器。这对于调试非常有用。 CacheWriter 可以检查是否设置了插入时间戳,如果是,则是更新,如果不是,则是插入。

如果您的应用程序正在通过缓存读取最新内容并写入它的修改版本,那么值是否同时被驱逐并不重要。

如果您的应用程序在修改前没有读取数据或者这种情况经常发生,我建议缓存一个类似 insertedAlready 的标志。这导致了三路逻辑:isnerted,未插入,不在缓存中=尚不知道。在这种情况下,您需要在更新或插入缓存写入器之前进行读取。

仅缓存中的元数据

缓存对象存储附加数据,无论该对象之前是否从数据库中读取过。喜欢:

class CachedDbValue<V> {
  boolean insertedAlready;
  V databaseContent;
}

面向您的应用程序的代码需要将数据库数据包装到缓存值中。

旁注 1: 不要从缓存中读取对象并直接修改实例,始终进行复制。直接修改对象可能会对不同的 JCache 实现产生不同的不良影响。还可以在这里查看我的解释:javax.cache store by reference vs. store by value

旁注 2: 您正在自己构建缓存 ORM 层。也许使用现有的。