1

I am using Spring Boot, Spring Data, with QueryDSL. Most of my queries are QueryDSL based. I want to implement a simple cache that stores User queries, and once a single entity is updated/saved then the entire Cache is cleared.

So here is my Repository Interface:

@Repository
@CacheConfig(cacheNames = "us")
public interface UserRepository extends JpaRepository<User, Long>, QueryDslPredicateExecutor<User> {


    @Cacheable
    List<User> findAll();

    @Override
    @Cacheable
    List<User> findAll(Sort sort);

    @Override
    @Cacheable
    List<User> findAll(Iterable<Long> longs);

    @Override
    @CacheEvict(allEntries = true)
    <S extends User> List<S> save(Iterable<S> entities);

    @Override
    @CacheEvict(allEntries = true)
    <S extends User> S saveAndFlush(S entity);

    @Override
    @Cacheable
    Page<User> findAll(Pageable pageable);

    @Override
    @CacheEvict(allEntries = true)
    <S extends User> S save(S entity);

    @Override
    @Cacheable
    User findOne(Long aLong);

    @Override
    @Cacheable
    Iterable<User> findAll(Predicate predicate);

    @Override
    @Cacheable
    User findOne(Predicate predicate);

    @Override
    @Cacheable
    Iterable<User> findAll(Predicate predicate, Sort sort);

    @Override
    @Cacheable
    Page<User> findAll(Predicate predicate, Pageable pageable);
}

As you can see I have cached all "Find" methods and using Save methods to Evict all entries. Usually the ones used are:

Page<User> findAll(Predicate predicate, Pageable pageable);
<S extends User> S save(S entity);

The Caching is set exclusively on the repositories, nothing on Services/Controllers etc.

Here is my config:

    @Bean
    public CacheManager cacheManager() {
        GuavaCacheManager manager = new GuavaCacheManager();
        CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder()
                .removalListener(new RemovalListener<Object, Object>() {
                    @Override
                    public void onRemoval(RemovalNotification<Object, Object> notification) {
                        LOG.info("Cache evicted: " + notification);
                    }
                })
                .maximumSize(100);
        manager.setCacheBuilder(builder);
        return manager;
    }

    @Bean
    public KeyGenerator keyGenerator() {
        return new SimpleKeyGenerator();
    }

I should also add that the User entity has a couple of subclasses but I am querying everything with the UserRepository

The problem is that even though my Search requests are successfully cached the cache is never evicted when I perform a save.

Anything I'm doing wrong?

ChrisGeo
  • 3,807
  • 13
  • 54
  • 92
  • The caching won't work as you expect, it will cache the result of the method invocation, it will NOT cache individual `User` objects. I strongly suggest to use the hibernate 2nd level caching for this instead of Springs cache abstraction (that has a different purpose). – M. Deinum Feb 04 '16 at 11:55
  • This is interesting: I stumbled at this problem too, so I can definitely confirm that this does not work as expected. – Ljudevit Nov 29 '17 at 13:10

0 Answers0