当前位置: 首页 > 知识库问答 >
问题:

@共享缓存上的可缓存密钥?

公冶嘉茂
2023-03-14

我有一个Spring应用程序,它使用MyBatis进行持久化。我使用ehcache是因为速度对于这个应用程序很重要。我已经设置并配置了MyBatis和Ehcache。我使用一个名为“mybatis”的单一缓存,因为否则为每个实体创建单独的缓存将是荒谬的。

这是我的电子缓存。xml。

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd"
         updateCheck="false"
         monitoring="autodetect"
         dynamicConfig="true">

    <diskStore path="java.io.tmpdir" />

    <cache name="mybatis"
           maxBytesLocalHeap="100M"
           maxBytesLocalDisk="1G"
           eternal="false"
           timeToLiveSeconds="0"
           timeToIdleSeconds="0"
           statistics="true"
           overflowToDisk="true"
           memoryStoreEvictionPolicy="LFU">
    </cache>

    <cache name="jersey"
           maxBytesLocalHeap="100M"
           maxBytesLocalDisk="1G"
           eternal="false"
           timeToLiveSeconds="600"
           timeToIdleSeconds="300"
           statistics="true"
           overflowToDisk="true"
           memoryStoreEvictionPolicy="LFU">
    </cache>

</ehcache>

这是我的mybatis映射器界面的一个示例。

import java.util.List;

public interface InstitutionMapper {

    @Cacheable(value = "mybatis")
    List<Institution> getAll();

    @Cacheable(value = "mybatis", key = "id")
    Institution getById(long id);

    @CacheEvict(value = "mybatis")
    void save(Institution institution);

    @CacheEvict(value = "mybatis", key = "id")
    void delete(long id);
}

因为我有一个共享缓存,所以我需要一种方法使我的密钥对域对象是唯一的。作为保存或删除的示例,我需要清除缓存,以便新值显示在UI上。但是,我不想清除整个缓存。我不知道如何处理这个问题,这样当调用delete并退出缓存时,只有带有该ID的for机构的mybatis缓存中的条目才会被清除。

密钥需要类似于域名参数。作为一个例子,机构id。希望这是有意义的。

我看过这篇文章,但它似乎是通过类名方法params来实现的。

共有1个答案

鲁熙云
2023-03-14

为整个域模型设置一个区域有点奇怪(至少可以这么说)。我可以想象你可以在同一个缓存中收集具有相似语义学的对象类型,但不是所有的对象类型。如果你有一个适当的界限,你在这里问的大多数问题都会自行解决。

但是为了解释,这里有一些想法。

您的getAll()需要密钥。如果不提供参数,则基本上任何其他无参数的@Cacheable方法都会与缓存中的同一个键冲突。

@Cacheable(value = 'mybatis', key = "'institutions'")
List<Institution> getAll();

您的@cacheexecute不会清除缓存列表(从getAll()方法),因此您可能处于这样的情况:您驱逐了一家机构,但它仍然会从缓存的getAll()调用中显示。如果要在多个级别缓存相同的内容,最好在更新/删除内容时删除整个区域。如果每个实体类型都有一个区域,那么这当然不是什么问题。

您的save方法没有id。它到底应该退出什么?它如何知道必须通过id查找现有机构?

@CacheEvict(value = "mybatis", key = "#p0.id")
void save(Institution institution);

(这并不能解决getAll()不一致的问题)

您的getById不需要密钥,因为唯一的方法参数是id。回到您最初的“问题”上,如果您想在密钥前加上前缀,您需要全面执行(以便逐出操作针对同一个密钥)。我不会在斯佩尔这样做,因为忘记一个案例的机会太高了。

您可以实现一个自定义的keyrolver,并根据方法的返回类型附加一个唯一的前缀。

话虽如此,您的示例代码离全部错误很近,因此我建议您查看关于此主题的留档

 类似资料:
  • 我正在使用WildFly 8.1,所以JPA 2.1和Hibernate 4.3.5 我想在WildFly中使用JPA共享缓存/二级缓存 我遵循WildFly文档:https://docs.jboss.org/author/display/WFLY8/JPA参考指南#使用InfinispanSecondlevelCache的JPA参考指南 这是我的persitience.xml: 我将属性设置为h

  • 我有两个应用程序使用相同的数据库实体。这两个应用程序都部署在jboss eap 6.2独立的集群上。DB表仅从一个应用程序中更新,但从两个应用程序中读取。这两个应用程序都使用本机hibernate API从数据库读取/写入数据。 在嵌入式模式下将infinispan启用为2LC后,如何确保在一个应用程序中更新的缓存实体从第二个应用程序缓存中失效?是否有任何JMX/JMS接口用于信号缓存失效? 若我

  • 问题内容: 我正在尝试EXPLAIN命令,并试图找出它是什么。 我注意到,共享的匹配数越多,我们执行查询的速度就越快。那是什么 据我了解,它只是从诸如或的物理存储中读取。但是为什么更快呢?它存储在RAM内还是在哪里? 问题答案: 本质上意味着该值已经被缓存在计算机的主存储器中,而不必从硬盘读取该值。 访问主内存(RAM) 的 速度比从硬盘读取值快得多。这就是为什么查询的点击次数越多,查询速度就越快

  • 我正在使用注释来缓存我的方法的结果。出于性能原因,我想缓存从方法返回的和非null值。 但是这里的问题是Spring缓存非空值,但由于某种原因没有缓存空值。 这是我的密码: 我什么都试过了。就连我 但这也没什么帮助。有关于这个的指示吗?

  • 我在Spring3.1中使用@Cacheable。我对Cacheable中的值和键映射参数有点混淆。以下是我正在做的: 这里发生的情况是,第二个方法依赖于第一个方法的选定值,但问题是假设当我传递zoneMastNo=1和areaMastNo=1时,第二个方法返回第一个方法结果。事实上,我有很多服务,因此,我希望使用公共值来缓存特定的用例。现在我的问题是: 我如何解决这个问题 对每个服务都使用cac

  • 当你使用本地(在内存中)缓存时,服务器可以缓存一些信息并快速地检索它,但是其他服务器不能访问这个缓存数据,他们需要到数据库中查询同样的信息。 如果你喜欢使用分布式缓存让其他服务器访问缓存的数据,由于它有一些序列化/反序列化和网络延迟开销,则需要注意:在某些情况下,它可能会降低性能。 缓存需要处理的另一个问题:缓存失效。 There are only two hard things in Compu