MongoDB Spring Data Repository - 缓存方法

che*_*ist 3 java spring mongodb spring-data spring-data-mongodb

我需要使用 spring @Cacheable 注释缓存对 MongoDB 的调用:

public interface SiteRepository extends PagingAndSortingRepository<Site, String>{
    @Cacheable
    List<Site> findByStatus(Site.Status status);
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,使用@Cacheable 注释接口中的任何方法会导致以下异常:

2014 年 11 月 22 日下午 7:11:06 org.apache.catalina.core.ApplicationContext 日志严重:StandardWrapper.Throwable org.springframework.beans.factory.BeanCreationException:创建名为“example”的 bean 时出错:注入自动装配的依赖项失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配字段:com.example.repositories.mongodb.SiteRepository com.example.siteRepo; 嵌套异常是 org.springframework.beans.factory.BeanCreationException:创建名为“siteRepository”的 bean 时出错:FactoryBean 的单例对象的后处理失败;嵌套异常是 org.springframework.aop.framework.AopConfigException:无法生成类 [class com.sun.proxy.$Proxy92] 的 CGLIB 子类:此问题的常见原因包括使用 final 类或不可见类;嵌套异常是 java.lang.IllegalArgumentException:无法在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289) 上的 org.springframework.beanPostProcessor.java:289 上子类化最终类类 com.sun.proxy.$Proxy92 factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1147) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) 在 org.springframework.CapableBeans.tractFactoryBeansupport. AbstractAutowireCapableBeanFactory.java:458) 在 org.springframework.beans.factory.support。1103) 在 org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1010) 在 org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4935) 在 org.apache.catalina.core.StandardContext $3.call(StandardContext.java:5262)​​ at org.apache.catalina.core.StandardContext$3.call(StandardContext.java:5257) at java.util.concurrent.FutureTask.run(Unknown Source) at java.util.concurrent .ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) 引起:org.springframework.beans.factory.BeanCreationException:可以不是自动装配字段:com.example.repositories.mongodb.SiteRepository com.example.siteRepo;嵌套异常是 org.springframework.beans.factory.BeanCreationException:创建名为“siteRepository”的 bean 时出错:FactoryBean 的单例对象的后处理失败;嵌套异常是 org.springframework.aop.framework.AopConfigException:无法生成类 [class com.sun.proxy.$Proxy92] 的 CGLIB 子类:此问题的常见原因包括使用最终类或不可见类;嵌套异常是 java.lang.IllegalArgumentException:无法在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:517) 处对最终类类 com.sun.proxy.$Proxy92 进行子类化。 beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor。postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286) ... 27 导致:org.springframework.beans.factory.BeanCreationException:创建名为“siteRepository”的 bean 时出错:FactoryBean 的单例对象的后处理失败;嵌套异常是 org.springframework.aop.framework.AopConfigException:无法生成类 [class com.sun.proxy.$Proxy92] 的 CGLIB 子类:此问题的常见原因包括使用最终类或不可见类;嵌套异常是 java.lang.IllegalArgumentException:无法在 org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:115) 处对 org.springframework.beans 处的最终类类 com.sun.proxy.$Proxy92 进行子类化。 factory.support.AbstractBeanFactory。29 导致:org.springframework.aop.framework.AopConfigException:无法生成类 [class com.sun.proxy.$Proxy92] 的 CGLIB 子类:此问题的常见原因包括使用最终类或不可见类; 嵌套异常是 java.lang.IllegalArgumentException:无法在 org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:218) 处的 org.springframework.aop.framework 处子类化最终类类 com.sun.proxy.$Proxy92。 ProxyFactory.getProxy(ProxyFactory.java:109) 在 org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:477) 在 org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfAutoNecessary(AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:477) 362) 在 org.springframework.aop.framework.autoproxy。

我正在寻找一种方法来缓存对 DB 的调用(这非常昂贵)。任何的想法?

ESa*_*ala 6

From the Spring documentation on caches:

Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the @Cache* annotation, as opposed to annotating interfaces. You certainly can place the @Cache* annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies. The fact that Java annotations are not inherited from interfaces means that if you are using class-based proxies ( proxy-target-class="true") or the weaving-based aspect ( mode="aspectj"), then the caching settings are not recognized by the proxying and weaving infrastructure, and the object will not be wrapped in a caching proxy, which would be decidedly bad.

可能您的缓存配置与 Spring 在运行时创建存储库接口的实现方式相冲突。

您可以查看缓存配置以使其与 spring 数据配合使用(有关不同的缓存配置选项,请参见此处)。

或者,你可以这样做:

public interface SiteRepository extends PagingAndSortingRepository<Site, String>{
    List<Site> findByStatus(Site.Status status);
}

@Service
public class CachedSiteService {

    @Autowired
    private SiteRepository siteRepository;

    @Cacheable("sites")
    List<Site> findByStatus(Site.Status status) {
        return siteRepository.findByStatus(status);
    }

}
Run Code Online (Sandbox Code Playgroud)