简体   繁体   中英

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

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). Unfortunately caching is not working when calling the repo method 'findByName'. Changing the caching mode to AdviceMode.PROXY all works fine.

To ensure that caching works in principle with aspectJ, i wrote the following service:

@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. 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:

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.

So it's not possible to use the @Cacheable annotation inside repository interfaces together with aspectj. My solution now is to make use of custom implementations for Spring Data repositories :

Interface for custom repository functionality:

public interface LandRepositoryCustom {

    Land findByNameCached(String land);
}

Implementation of custom repository functionality using query 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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