【问题标题】:Spring cache abstraction (AdviceMode.ASPECTJ) not working inside spring-data-jpa repositoriesSpring 缓存抽象(AdviceMode.ASPECTJ)在 spring-data-jpa 存储库中不起作用
【发布时间】:2015-12-29 07:06:17
【问题描述】:

我正在使用 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 缓存模式的组合。有谁知道这里出了什么问题?

【问题讨论】:

    标签: java caching spring-data aspectj aspectj-maven-plugin


    【解决方案1】:

    好的,我自己找到了我的问题的答案。负责方面 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");
      }
    }
    

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

    【讨论】:

    • 不幸的是,如果您想在保存实体时逐出缓存,我的解决方案不起作用,请参阅@oliver-gierke 的this 帖子。这是因为我们不能用 CacheEvict 注解来注解 CrudRepository 接口的方法 S save(S entity) 。我想这个问题不容易解决……
    猜你喜欢
    • 2012-04-12
    • 2019-03-02
    • 1970-01-01
    • 2012-06-02
    • 1970-01-01
    • 1970-01-01
    • 2018-08-06
    • 2017-11-22
    • 1970-01-01
    相关资源
    最近更新 更多