java ehcache + spring — не кешується один метод

💡 Усі статті, обговорення, новини про Java — в одному місці. Приєднуйтесь до Java спільноти!

привіт всім
проблема з тим що не кешуються деякі методи.. а деякі кешуються.

---------------------------------------------------------------------------------------------------

 
    class MdxQueryExecutor implements Query {
    @Override
    @Cacheable(CACHE_QUERY)
    public CellSet executeStoredQuery(AbstractDashboardService service, String queryName, CommonParameters params, Object... values) {
        System.out.println("2");
        return null;
}

    @Override
    @Cacheable(CACHE_QUERY)
    public CellSet executeQuery(String query) {
        System.out.println("sdasdas");
        return null;

}
---------------------------------------------------------------------------------------------------
    @Autowired
    Query query; \\ це інтерфейс
    @Test
    public void mdxQueryTest() {
   

        query.executeStoredQuery( null, "", new CommonParameters());
        query.executeStoredQuery( null, "", new CommonParameters());
        
        query.executeQuery("");
        query.executeQuery("");

    }
---------------------------------------------------------------------------------------------------
executeQuery — кешується нормально
executeStoredQuery — не кешується.. !!!! ну чому???
---------------------------------------------------------------------------------------------------
     <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false"
         maxBytesLocalHeap="500M"
         maxBytesLocalDisk="2G">

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

    <cache name="query"
           eternal="false"
           timeToIdleSeconds="0"
           timeToLiveSeconds="86400"
           memoryStoreEvictionPolicy="LRU"
           overflowToDisk="true"
           diskPersistent="false"
           statistics="true"/>           
         
</ehcache>
---------------------------------------------------------------------------------------------------
      <dependency>
            <groupId>com.googlecode.ehcache-spring-annotations</groupId>
            <artifactId>ehcache-spring-annotations</artifactId>
            <version>1.2.0</version>
        </dependency>
👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

дякую..
1) де в мене втрата пам’яті?
2) а якщо так

executeStoredQuery(AbstractDashboardService service, String queryName, CommonParameters params, Object... values) {
return executeQuery("bla");
}

@Override
@Cacheable(CACHE_QUERY)
public CellSet executeQuery(String query)

чому в такому разі воно не хоче кешувати?
в мануалах що доступ має бути через інтерфейс та ще й інстанс має бути через спрінг(принаймні воно в мене тільки так і працює. Якщо я роблю інстанс вручну то воно не працює)
принаймні з другим пунктом можна щось зробити, щоб працював код зверху?

1) не факт що буде, але майте на увазі, що всі елементи що передаються як параметри, враховуючи

AbstractDashboardService
будуть використовуватись як частини ключа і з кешу буде зберігатись на них посилання. Наприклад на
AbstractDashboardService
. Допускаю що він сінглтон, що існує на весь час існування програми, але все одно, навіщо тримати посилання на нього з кеша? Через нього може і не працювати. Але можливо не працює не тільки через нього.

2) спробуйте забрати всі не об’єкти даних з параметрів, наприклад посилання на сервіс можете зробити полем вашого класу. Слідкуйте щоб об’єкти у params і values мали нормальний стабільний equals & hashCode, такий що логічно однакові об’єкти передані у різний час вважались однаковими

проблема в вараргс, в масивах не може бути іквелса і хеш кода(ну і в тому що немає equals і хеш кода для деяких класів.)
так, ви праві, абстракні класи краще не сунути в кеш.

2) я напевно погано пояснив проблема

--------------------------------------------------------------------------------------------------
@Autowired
QueryTest query;

query.executeQuery("bla") — так працює
--------------------------------------------------------------------------------------------------
QueryTest query = new MdxDashboardsQuery();
query.executeQuery("bla") — так НЕ працює
--------------------------------------------------------------------------------------------------

чи можливо якось зробити так щоб мені не потрібно було інстанціювати клас в спрінгу щоб скористатись кешем?

1) заверніть вараргс у свій клас, що комбінує хешкоди елементів. Кешуйте інший метод, в який передається цей об’єкт, а не той що в вараргс.

2) коли ви отримуєте доступ через Spring, він повертає не ваш об’єкт, а згенерований динамічний проксі на нього. Якщо ви самі створюєте об’єкт, цього не відбувається. Тому у пункті 1) вам необхідно викликати кешований метод теж церез інтерфейс, з іншого Spring біна

дуже дякую. Так і зроблю

Ключ для кеша будет формироваться из хешкодов параметров. Ну и equals. Для String все просто. Но в другом методе у тебя там не для всех объектов их можно вычислить, некоторые классы скорее всего их не переопределяют просто потому что они не классы данных. Туда приходят постоянно новые инстансы и каждый раз не находят ничего в кеше и создают новый элемент в кеше.

У тебя не только кеширование на работает, еще и утечка памяти (со скидкой на очистку кеша)

Может, дело вот в этом:
docs.spring.io/...ble-default-key
?

Підписатись на коментарі