1

我正在使用 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 方法“findByName”时缓存不起作用。将缓存模式更改为 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 缓存模式的组合。有谁知道这里出了什么问题?

4

1 回答 1

2

好的,我自己找到了我的问题的答案。负责方面 org.springframework.cache.aspectj.AnnotationCacheAspect 的 javadoc 说:

使用此方面时,您必须注释实现类(和/或该类中的方法),而不是该类实现的接口(如果有)。AspectJ 遵循 Java 的规则,即不继承接口上的注释。

所以不可能在存储库接口中使用@Cacheable 注释和aspectj。我现在的解决方案是使用Spring Data 存储库的自定义实现

自定义存储库功能的接口:

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");
  }
}

在 spring 数据参考中添加与此限制相关的注释会很有帮助。

于 2015-10-01T12:13:42.967 回答