跳到主要内容

缓存未生效的原因

CacheAbandonedCallback

按照前面文档的阐述,使用多视图缓存相对严苛,必须同时满足以下3个条件

  1. 必须明确为需要属性置顶多视图缓存。

    缓存是多层的,需要为用于构建缓存实例的ChainCacheBuilder<K, V>指定多个Binder对象,即LoadingBinder/KLoadingBinderSimpleBinder/KSimpleBinder

    对于多视图缓存而言,所有Binder对象都必须实现LoadingBinder.Parameterized<K, V>/KLoadingBinder.Parameterized<K, V>SimpleBinder.Parameterized<K, V>/KSimpleBinder.Parameterized<K, V>接口。否则,最终ChainCacheBuilder<K, V>创建的缓存是单视图缓存。

  2. 关联属性的过滤规则和计算属性的计算规则必须支持缓存友好。

    • 对于关联属性而言,影响其关联对象的 所有 全局过滤器必须是缓存友好的过滤器。任何一个过滤器不对缓存友好都可能导致该属性无法使用缓存。

      • 对于用户自定义的缓存过滤器而言,必须实现CacheableFilter<E>/KCacheableFilter<E>接口。

      • 对于软删除注解@LogicalDeleted而言,必须将其属性useMultiViewCache配置为true(这会导致其内置全局过滤器实现CacheableFilter<E>/KCacheableFilter<E>接口)

    • 对于计算属性而言,其TransientResolver<ID, V>/KTransientResolver<ID, V>的方法getParameterMapRef不得返回null。

  3. 对象抓取器不使用属性级过滤器

如果这些前提条件并未完全满足,即便为关联属性或计算属性指定了缓存,Jimmer也会弃之不用。虽然前面的文档详细解释过原因,但实际开发中遇到这类问题时排查不方便。

为了让开发人员快速得知属性级缓存未生效的事实及其原因,Jimmer定义了一个回调接口,如下

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

该回调接口告诉开发人员,虽然某个属性的缓存被指定了但并未被Jimmer所采纳,以及原因。其abandoned方法具备两个参数

  • prop: 哪个属性并为采纳用户配置的缓存。

  • reason:该属性的缓存未被采纳的原因,有以下三种可能:

    • CACHEABLE_FILTER_REQUIRED: 关联对象受到某些全局过滤器的影响,但并非所有过滤器都实现了CacheableFilter<E>/KCacheableFilter<E>接口。

    • PARAMETERIZED_CACHE_REQUIRED: 影响关联属性的某些CacheableFilter<E>/KCacheableFilter<E>对象的getParameters方法或实现计算属性的TransientResolver<ID, V>/KTransientResolver<ID, V>getParameterMapRef方法返回了长度非0的Map, 但是,开发人员并未为该属性配置的缓存并不是多视图缓存。

    • FIELD_FILTER_USED: 开发人员对属性使用了对象抓取器中的属性级过滤器。

开发人员可以自己实现CacheAbandonedCallback接口,创建对象并将其注册到SqlClient中。被注册的回调对象数量无限制。

注册Callback

有两种方法可以为Jimmer注册CacheAbandonedCallback

  • 使用Spring Boot Starter

    只需用@Component修饰CacheAbandonedCallback的实现类即可

    @Component
    public class MyCallback implements CacheAbandonedCallback {
    ...省略代码...
    }
  • 使用底层API

    JSqlClient sqlClient = 
    JSqlClient
    .newBuilder()
    .addCacheAbandonedCallback(
    new CacheAbandonedCallback() {
    ...省略代码...
    }
    )
    ...省略其他配置...
    .build();

Spring Boot Starter默认行为

如果用户并未注册任何callback实现,Spring Boot Starter会默认注册一个Callback实现,将缓存未被采纳的原因作为警告日志输出,例如:

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