我有一个使用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。
答案 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