如何在 Spring Data JPA CRUDRepository 中添加缓存功能

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13914480/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:36:04  来源:igfitidea点击:

How to add cache feature in Spring Data JPA CRUDRepository

springhibernatecachingjpajdbc

提问by virsir

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

我想在 findOne 方法中添加“Cacheable”注释,并在发生删除或发生方法时驱逐缓存。

How can I do that ?

我怎样才能做到这一点 ?

回答by seven

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:

virsir,如果您使用 Spring Data JPA(仅使用接口),还有另一种方法。这是我所做的,类似结构化实体的通用 dao:

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);
}

回答by Warren Zhu

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

我认为基本上@seven 的答案是正确的,但有 2 点缺失:

  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. saveand deleteshould be CachePut, and findAllshould be both Cacheableand 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);
    }
    
  1. 我们无法定义通用接口,恐怕我们必须单独声明每个具体接口,因为注解不能被继承,而且我们需要为每个存储库使用不同的缓存名称。

  2. save并且delete应该是CachePut,并且findAll应该是CacheableCacheEvict

    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

参考

回答by Sujeet

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 {

}

回答by Maksym Demidas

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:

尝试提供 MyCRUDRepository(一个接口和一个实现),如下所述:向所有存储库添加自定义行为。然后,您可以覆盖并为这些方法添加注释:

findOne(ID id)
delete(T entity)
delete(Iterable<? extends T> entities)
deleteAll() 
delete(ID id)