简体   繁体   English

Spring缓存抽象(AdviceMode.ASPECTJ)在spring-data-jpa存储库中不起作用

[英]Spring cache abstraction (AdviceMode.ASPECTJ) not working inside spring-data-jpa repositories

i'm using spring-data-jpa 1.9.0.RELEASE and want to use the spring caching mechanism inside my repositories, eg 我正在使用spring-data-jpa 1.9.0.RELEASE,并想在我的存储库中使用spring缓存机制,例如

public interface LandDao extends CrudRepository<Land, Long> {

    @Cacheable("laender")
    Land findByName(String land)
}

Here is my cache configuration: 这是我的缓存配置:

@Configuration
@EnableCaching(mode=AdviceMode.ASPECTJ)
public class EhCacheConfiguration extends CachingConfigurerSupport {
...

Note that i'm using AdviceMode.ASPECTJ (compile time weaving). 请注意,我正在使用AdviceMode.ASPECTJ(编译时间编织)。 Unfortunately caching is not working when calling the repo method 'findByName'. 不幸的是,当调用repo方法'findByName'时,缓存不起作用。 Changing the caching mode to AdviceMode.PROXY all works fine. 将缓存模式更改为AdviceMode.PROXY都可以正常工作。

To ensure that caching works in principle with aspectJ, i wrote the following service: 为了确保缓存原则上可以与AspectJ一起使用,我编写了以下服务:

@Service
public class LandService {

  @Autowired
  LandDao landDao;

  @Cacheable("landCache")
  public Land getLand(String bez) {
    return landDao.findByName(bez);
  }
}

In this case the cache works like a charm. 在这种情况下,缓存就像一个超级按钮一样工作。 So i think that all parts of my application are correctly configured and the problem is the combination of spring-data-jpa and AspectJ caching mode. 因此,我认为应用程序的所有部分均已正确配置,问题是spring-data-jpa和AspectJ缓存模式的组合。 Does anyone have an idea what's going wrong here? 有人知道这里出了什么问题吗?

Okay, found the answer to my question by myself. 好的,我自己找到了我问题的答案。 The javadoc of the responsible aspect org.springframework.cache.aspectj.AnnotationCacheAspect says: 负责方面org.springframework.cache.aspectj.AnnotationCacheAspect的Javadoc说:

When using this aspect, you must annotate the implementation class (and/or methods within that class), not the interface (if any) that the class implements. 使用此方面时,必须注释实现类(和/或该类中的方法),而不是注释该类所实现的接口(如果有)。 AspectJ follows Java's rule that annotations on interfaces are not inherited. AspectJ遵循Java的规则,即不继承接口上的注释。

So it's not possible to use the @Cacheable annotation inside repository interfaces together with aspectj. 因此,不可能将存储库接口内的@Cacheable注释与Aspectj一起使用。 My solution now is to make use of custom implementations for Spring Data repositories : 我现在的解决方案是对Spring Data存储库使用自定义实现

Interface for custom repository functionality: 定制存储库功能的接口:

public interface LandRepositoryCustom {

    Land findByNameCached(String land);
}

Implementation of custom repository functionality using query dsl: 使用查询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);
  }
}

Note the @Cacheable annotation for the findByNameCached method. 注意findByNameCached方法的@Cacheable批注。

Basic repository interface: 基本存储库界面:

public interface LandRepository extends CrudRepository<Land, Long>, LandRepositoryCustom {
}

Using the repository: 使用存储库:

public class SomeService {

  @Autowired
  LandRepository landDao;

  public void foo() {
    // Cache is working here:-)
    Land land = landDao.findByNameCached("Germany");
  }
}

It would be helpful to add a note relating to this limitation in the spring data reference. 在弹簧数据参考中添加与此限制有关的注释会很有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM