Skip to main content

Cache Abandoned Reason

CacheAbandonedCallback

Using multi-view caches is relatively strict and the following three conditions must be met at the same time:

  1. The properties that need multi-view cache must be explicitly specified.

    Cache is multi-layered. Multiple Binder objects must be specified for the ChainCacheBuilder<K, V> used to build the cache instance, i.e. LoadingBinder/KLoadingBinder or SimpleBinder/KSimpleBinder.

    For multi-view caches, all Binder objects must implement the LoadingBinder.Parameterized<K, V>/KLoadingBinder.Parameterized<K, V> or SimpleBinder.Parameterized<K, V>/KSimpleBinder.Parameterized<K, V> interface. Otherwise, the final cache created by ChainCacheBuilder<K, V> is a single-view cache.

  2. The filtering rules for association properties and the calculation rules for calculated properties must be cache friendly.

    • For association properties, all global filters that affect their associated objects must be cache friendly filters. If any one filter is not cache friendly, it may cause the all affected properties to be unable to use cache.

      • For user-defined cache filters, the CacheableFilter<E>/KCacheableFilter<E> interface must be implemented.

      • For the @LogicalDeleted, its useMultiViewCache property must be configured as true (this will cause its built-in global filter to implement the CacheableFilter<E>/KCacheableFilter<E> interface).

    • For calculated properties, the getParameterMapRef method of TransientResolver<ID, V>/KTransientResolver<ID, V> must not return null.

  3. The object fetch cannot use property-level filters.

If these prerequisite conditions are not fully met, even if cache is specified for association or calculated properties, Jimmer will abandon them. Although the reasons have been explained in detail in previous documents, troubleshooting such issues during actual development is inconvenient.

To quickly inform developers of the fact that property-level cache did not take effect and the reason, Jimmer defines a callback interface as follows:

package org.babyfish.jimmer.sql.cache;

import org.babyfish.jimmer.meta.ImmutableProp;

public interface CacheAbandonedCallback {

void abandoned(ImmutableProp prop, Reason reason);

enum Reason {

CACHEABLE_FILTER_REQUIRED,

PARAMETERIZED_CACHE_REQUIRED,

FIELD_FILTER_USED
}
}

This callback interface tells developers that although cache is specified for a property, it is not adopted by Jimmer, and the reason. Its abandoned method has two parameters:

  • prop: Which property does not adopt the cache configured by the user.

  • reason: The reason why the cache of this property is not adopted. There are three possible values:

    • CACHEABLE_FILTER_REQUIRED: The associated objects are affected by some global filters, but not all filters implement the CacheableFilter<E>/KCacheableFilter<E> interface.

    • PARAMETERIZED_CACHE_REQUIRED: The getParameters method of some CacheableFilter<E>/KCacheableFilter<E> objects affecting the association properties or the getParameterMapRef method of TransientResolver<ID, V>/KTransientResolver<ID, V> implementing the calculated properties returns a Map of non-zero length, but the cache configured for that property by the developer is not a multi-view cache.

    • FIELD_FILTER_USED: The developer uses property-level filters for the property in object fetchers.

Developers can implement the CacheAbandonedCallback interface themselves, create an object, and register it with SqlClient. There is no limit on the number of registered callback objects.

Registering Callback

There are two ways to register CacheAbandonedCallback for Jimmer:

  • Using Spring Boot Starter

    Just decorate the implementation class of CacheAbandonedCallback with @Component:

    @Component
    public class MyCallback implements CacheAbandonedCallback {
    ...omit code...
    }
  • Using underlying API

    JSqlClient sqlClient =
    JSqlClient
    .newBuilder()
    .addCacheAbandonedCallback(
    new CacheAbandonedCallback() {
    ...omit code...
    }
    )
    ...omit other configuration...
    .build();

Default Behavior of Spring Boot Starter

If no callback implementation is registered by the user, the Spring Boot Starter will register a default callback implementation by default, outputting the reason why the cache is not adopted as a warning log, for example:

!!!Jimmer warning!!!
Property-level cache is abandoned.
Property: `com.yourcompany.yourproject.model.BookStore.books`
Reason: CACHEABLE_FILTER_REQUIRED