我使用spring-data-jpa 1.9.0.RELEASE并希望在我的存储库中使用spring缓存机制,例如。
public interface LandDao extends CrudRepository<Land, Long> {
@Cacheable("laender")
Land findByName(String land)
}
这是我的缓存配置:
@Configuration
@EnableCaching(mode=AdviceMode.ASPECTJ)
public class EhCacheConfiguration extends CachingConfigurerSupport {
...
请注意,我使用AdviceMode.ASPECTJ(编译时编织)。不幸的是,在调用repo方法时,缓存无法正常工作&#39; findByName&#39;。 将缓存模式更改为AdviceMode.PROXY一切正常。
为确保缓存原则上与aspectJ一起工作,我编写了以下服务:
@Service
public class LandService {
@Autowired
LandDao landDao;
@Cacheable("landCache")
public Land getLand(String bez) {
return landDao.findByName(bez);
}
}
在这种情况下,缓存就像魅力一样。所以我认为我的应用程序的所有部分都已正确配置,问题是spring-data-jpa和AspectJ缓存模式的组合。有没有人知道这里出了什么问题?
答案 0 :(得分:2)
好的,我自己找到了问题的答案。负责方面org.springframework.cache.aspectj.AnnotationCacheAspect的javadoc说:
使用此方面时,必须注释实现类(和/或该类中的方法),而不是该类实现的接口(如果有)。 AspectJ遵循Java的规则,即接口上的注释不会被继承。
因此,不可能在存储库接口中使用@cacheable注释以及aspectj。我现在的解决方案是使用custom implementations for Spring Data repositories:
自定义存储库功能的接口:
public interface LandRepositoryCustom {
Land findByNameCached(String land);
}
使用查询dsl实现自定义存储库功能:
@Repository
public class LandRepositoryImpl extends QueryDslRepositorySupport
implements LandRepositoryCustom {
@Override
@Cacheable("landCache")
public Land findByNameCached(String land) {
return from(QLand.land).where(QLand.land.name.eq(land)).singleResult(QLand.land);
}
}
请注意findByNameCached方法的@Cacheable注释。
基本存储库界面:
public interface LandRepository extends CrudRepository<Land, Long>, LandRepositoryCustom {
}
使用存储库:
public class SomeService {
@Autowired
LandRepository landDao;
public void foo() {
// Cache is working here:-)
Land land = landDao.findByNameCached("Germany");
}
}
在弹簧数据参考中添加与此限制相关的注释会很有帮助。