首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >共享缓存上的@Cacheable密钥?

共享缓存上的@Cacheable密钥?
EN

Stack Overflow用户
提问于 2015-07-27 19:50:04
回答 1查看 1.8K关注 0票数 1

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

这是我的ehcache.xml。

代码语言:javascript
复制
<?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>

这里是我的mapper界面的一个示例。

代码语言:javascript
复制
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的执行机构的mybatis中的条目才被清除。

密钥需要类似于域名+ params。以机构+ id为例。希望这是合理的。

我看到了这篇文章,但它似乎是以类名+方法+ params的方式进行的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-28 12:55:43

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

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

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

代码语言:javascript
复制
@Cacheable(value = 'mybatis', key = "'institutions'")
List<Institution> getAll();

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

您的save方法没有id。它到底要驱逐什么?它怎么知道它必须通过id找到一个现有的机构?

代码语言:javascript
复制
@CacheEvict(value = "mybatis", key = "#p0.id")
void save(Institution institution);

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

您的getById不需要密钥,因为您拥有的唯一方法参数是,是id的。回到你最初的“问题”,如果你想在你的钥匙前加上一些东西,你需要全面地去做(这样驱逐就可以用同样的键了)。我不会在SpEL上这么做,因为有机会忘记一个案子太高了。

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

话虽如此,但您的示例代码几乎是错误的,所以我建议您检查一下有关此主题的文档

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31661986

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档