共享缓存上的@Cacheable密钥?

时间:2015-07-27 19:50:04

标签: java spring caching ehcache spring-cache

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

这是我的ehcache.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 mapper界面的示例。

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 Institution的mybatis缓存中的条目才会被清除。

密钥需要像域名+参数一样。作为一个例子机构+ id。希望这是有道理的。

我看过这篇文章,但似乎是按类名+方法+ params。

1 个答案:

答案 0 :(得分:3)

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

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

您的getAll()需要一把钥匙。如果你不提供一个,那么基本上没有参数的任何其他@Cacheable方法都会与缓存中的相同密钥冲突。

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

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

您的getAll()方法没有ID。什么应该完全驱逐?它如何知道必须通过id找到现有的机构?

save

(虽然没有解决@CacheEvict(value = "mybatis", key = "#p0.id") void save(Institution institution); 不一致的问题)

您的getAll()不需要密钥,因为您拥有的唯一方法参数 是ID。回到原来的&#34;问题&#34;,如果你想在你的钥匙前面加上一些东西,你需要全面地做(因此驱逐对着同一把钥匙)。我不会在SpEL那样做,因为忘记一个案子的机会太高了。

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

话虽如此,您的示例代码与所有错误接近,所以我建议您查看documentation on this topic

相关问题