缓存未生效的原因
CacheAbandonedCallback
按照前面文档的阐述,使用多视图缓存相对严苛,必须同时满足以下3个条件
-
必须明确为需要属性置顶多视图缓存。
缓存是多层的,需要为用于构建缓存实例的
ChainCacheBuilder<K, V>指定多个Binder对象,即LoadingBinder/KLoadingBinder或SimpleBinder/KSimpleBinder。对于多视图缓存而言,所有
Binder对象都必须实现LoadingBinder.Parameterized<K, V>/KLoadingBinder.Parameterized<K, V>或SimpleBinder.Parameterized<K, V>/KSimpleBinder.Parameterized<K, V>接口。否则,最终ChainCacheBuilder<K, V>创建的缓存是单视图缓存。 -
关联属性的过滤规则和计算属性的计算规则必须支持缓存友好。
-
对于关联属性而言,影响其关联对象的 所有 全局过滤器必须是缓存友好的过滤器。任何一个过滤器不对缓存友好都可能导致该属性无法使用缓存。
-
对于用户自定义的缓存过滤器而言,必须实现
CacheableFilter<E>/KCacheableFilter<E>接口。 -
对于软删除注解
@LogicalDeleted而言,必须将其属性useMultiViewCache配置为true(这会导致其内置全局过滤器实现CacheableFilter<E>/KCacheableFilter<E>接口)。
-
-
对于计算属性而言,其
TransientResolver<ID, V>/KTransientResolver<ID, V>的方法getParameterMapRef不得返回null。
-
-
对象抓取器不使用属性级过滤器。
如果这些前提条件并未完全满足,即便为关联属性或计算属性指定了缓存,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的实现类即可- Java
- Kotlin
@Component
public class MyCallback implements CacheAbandonedCallback {
...省略代码...
}@Component
class MyCallback : CacheAbandonedCallback {
...省略代码...
} -
使用底层API
- Java
- Kotlin
JSqlClient sqlClient =
JSqlClient
.newBuilder()
.addCacheAbandonedCallback(
new CacheAbandonedCallback() {
...省略代码...
}
)
...省略其他配置...
.build();val sqlClient = newKSqlClient {
addCacheAbandonedCallback(
object: CacheAbandonedCallback {
...省略代码...
}
)
...省略其他配置...
}
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