19

I want to add "Cacheable" annotation in findOne method, and evict the cache when delete or happen methods happened.

How can I do that ?

virsir
  • 15,159
  • 25
  • 75
  • 109

4 Answers4

13

virsir, there is one more way if you use Spring Data JPA (using just interfaces). Here what I have done, genereic dao for similar structured entities:

public interface CachingDao<T, ID extends Serializable> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {

@Cacheable(value = "myCache")
T findOne(ID id);

@Cacheable(value = "myCache")
List<T> findAll();

@Cacheable(value = "myCache")
Page<T> findAll(Pageable pageable);

....

@CacheEvict(value = "myCache", allEntries = true)
<S extends T> S save(S entity);

....

@CacheEvict(value = "myCache", allEntries = true)
void delete(ID id);
}
seven
  • 163
  • 3
  • 7
  • 2
    Can you please explain why you use `@CacheEvict` for the method `save`?? Why wouldn't you use `@CachePut`? Wouldn't saving it update the Cache correctly, and thus not require `@Cacheable` to even run after a save (assuming the cache is still there ofcourse) – taylorcressy Aug 29 '14 at 15:27
  • 2
    @seven nice! note that it is possible to annotate the `Repo` with `@CacheConfig` so the `cache` name will be outside of `CachingDao` – oak Oct 06 '15 at 09:03
  • 1
    To build on @delver's comment: "Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the @Cache* annotation, as opposed to annotating interfaces." See the source for more details -- http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html – jzonthemtn Nov 10 '16 at 12:30
  • 1
    Oddly Spring's own examples show using `@Cache*` annotations on interfaces ... https://github.com/spring-projects/spring-data-examples/blob/master/jpa/example/src/main/java/example/springdata/jpa/caching/CachingUserRepository.java – Snekse Aug 18 '17 at 16:26
  • Anyone know why you would evict all entires when saving or deleting a single record? – Snekse Aug 18 '17 at 16:30
  • @seven - Is there a way to write some code to update this cache managed by spring? I want to update the cache in a jms consumer implementation. – Andy Dufresne Mar 13 '18 at 12:48
9

I think basically @seven's answer is correct, but with 2 missing points:

  1. We cannot define a generic interface, I'm afraid we have to declare every concrete interface separately since annotation cannot be inherited and we need to have different cache names for each repository.

  2. save and delete should be CachePut, and findAll should be both Cacheable and CacheEvict

    public interface CacheRepository extends CrudRepository<T, String> {
    
        @Cacheable("cacheName")
        T findOne(String name);
    
        @Cacheable("cacheName")
        @CacheEvict(value = "cacheName", allEntries = true)
        Iterable<T> findAll();
    
        @Override
        @CachePut("cacheName")
        T save(T entity);
    
        @Override
        @CacheEvict("cacheName")
        void delete(String name);
    }
    

Reference

Warren Zhu
  • 1,355
  • 11
  • 12
  • I dont know why there is negative rating, but 1) is true and I guess that evic allentries is there because your cache may have as keys different values then PK, thus when modifiing record, you should specify what to evict - and if you have only PK, you dont know cache key, so you dont know which cache record invalidate – Cipous Mar 03 '16 at 14:23
5

I solved the this in the following way and its working fine


public interface BookRepositoryCustom {

    Book findOne(Long id);

}

public class BookRepositoryImpl extends SimpleJpaRepository<Book,Long> implements BookRepositoryCustom {

    @Inject
    public BookRepositoryImpl(EntityManager entityManager) {
        super(Book.class, entityManager);
    }

    @Cacheable(value = "books", key = "#id")
    public Book findOne(Long id) {
        return super.findOne(id);
    }

}

public interface BookRepository extends JpaRepository<Book,Long>, BookRepositoryCustom {

}
Sujeet
  • 143
  • 2
  • 10
2

Try provide MyCRUDRepository (an interface and an implementation) as explained here: Adding custom behaviour to all repositories. Then you can override and add annotations for these methods:

findOne(ID id)
delete(T entity)
delete(Iterable<? extends T> entities)
deleteAll() 
delete(ID id) 
Maksym Demidas
  • 7,707
  • 1
  • 29
  • 36