@Cacheable Key в общем кэше?

У меня есть приложение Spring, которое использует MyBatis для сохранения. Я использую 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.

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);
}

Поскольку у меня есть общий кеш, мне нужен способ, чтобы мои ключи были уникальными для объекта домена. В качестве примера при сохранении или удалении мне нужно очистить кеш, чтобы новые значения отображались в пользовательском интерфейсе. Однако я не хочу очищать весь кеш. Я не знаю, как подойти к этому, чтобы при вызове удаления и удалении кеша очищались только записи в кеше mybatis с for Institution с этим идентификатором.

Ключ должен быть чем-то вроде доменного имени + параметры. Например учреждение + id. Надеюсь, это имеет смысл.

Я видел этот пост, но, похоже, он идет по имени класса + методу + параметрам.


person greyfox    schedule 27.07.2015    source источник


Ответы (1)


Наличие единого региона для всей модели предметной области немного странно (по меньшей мере). Я могу себе представить, что вы можете собирать типы объектов с похожей семантикой в ​​одном и том же кэше, но не все типы объектов. Большинство вопросов, которые вы здесь задаете, разрешились бы сами собой, если бы у вас была надлежащая демаркация.

Но ради пояснения, вот некоторые мысли.

Вашему getAll() нужен ключ. Если вы его не предоставите, то практически любой другой метод @Cacheable без аргументов будет конфликтовать с тем же ключом в кеше.

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

Ваш @CacheEvict не будет очищать кешированный список (из метода getAll()), поэтому вы можете оказаться в ситуации, когда вы вытесняете учреждение, а оно все еще отображается из кэшированного getAll() вызова. Если вы хотите кэшировать одно и то же на нескольких уровнях, вам лучше удалить весь регион, когда вы что-то обновляете/удаляете. Это, конечно, не проблема, если у вас есть регион для каждого типа объекта.

Ваш метод save не имеет идентификатора. Что именно он должен выселять? Как он узнает, что должен найти существующее учреждение по идентификатору?

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

(хотя это не решит несоответствие getAll())

Ваш getById не требует ключа, поскольку единственный аргумент метода, который у вас есть, является идентификатором. Вернемся к вашей первоначальной «проблеме», если вы хотите добавить к своим ключам префикс, вам нужно сделать это по всем направлениям (чтобы вытеснение работало против одного и того же ключа). Я бы не стал этого делать в SpEL, так как шанс забыть один случай слишком высок.

Вы можете реализовать собственный KeyResolver и добавить уникальный префикс в соответствии с типом возвращаемого значения метода.

При этом ваш пример кода близок к тому, чтобы быть полностью неправильным, поэтому я бы посоветовал вам просмотреть документация по этой теме

person Stephane Nicoll    schedule 28.07.2015
comment
Спасибо за подробное объяснение. Похоже, что один кэш - это не очень хорошая идея и не обычная практика. Я думаю, что было бы лучше использовать отдельные области кеша или использовать поддержку MyBatis ehcache в моих файлах сопоставления MyBatis. - person greyfox; 28.07.2015