缓存JpaRepository中的方法(Spring Data)

时间:2018-04-23 03:31:28

标签: java spring spring-boot spring-data-jpa

工具: Spring-Boot:1.5.9.RELEASE Spring-Data-JPA:1.11.9.RELEASE

问题: 目前我有一个从JpaRepository扩展的存储库。为了避免频繁的DB访问,我想在JpaRepository中缓存一些CRUD方法。 我尝试了几种与Google先生无关的方法,但除了一个之外没有其他方法。

EDITED  1.此link中提到的解决方案是可行的。但是,这里有一个不好的做法(冗余给我)。想象一下,如果我有50个扩展JpaRepository的存储库,这意味着我必须覆盖50个存储库中的save方法。

     public interface UserRepository extends CrudRepository<User, Long> {
        @Override
        @CacheEvict("user")
        <S extends User> S save(S entity);

        @Cacheable("user")
        User findByUsername(String username);
     }

EDITED  2.扩展JpaRepository接口。我看到了link2可能有用的东西。

在链接中,它提到了缓存JpaRepository方法的3种不同方法。第一种方法与我在#1中提到的相同。但是,我想要类似于第二/第三种方法的东西,以便我无需继续重复覆盖所有存储库中的CRUD方法

以下是我编写的一些示例代码。

    @NoRepositoryBean        
    public interface BaseRepository<T, ID extends Serializable> extends 
    JpaRepository<T, ID> {

        @CacheEvict
        <S extends User> S save(S entity);

        @Cacheble
        T findOne(ID id);
    }

    @Repository
    @CacheConfig("user")
    public interface UserRepository extends BaseRepository<User, Integer> {
        // when I calling findOne/save method from UserRepository, it should 
        // caching the methods based on the CacheConfig name defined in the 
        // child class.
    }

然而,似乎代码(上面)不起作用,因为我得到了异常。我理解这个问题主要是因为没有为BaseRepository中的可缓存注释分配名称。但是我需要在从JpaRepository扩展的BaseRepository中缓存CRUD方法。

  

java.lang.IllegalStateException:无法解析'Builder [public abstract java.util.List com.sdsap.app.repository.BaseRepository.findAll()] caches = [] | key =''| keyGenerator =''| cacheManager =''| cacheResolver =''| condition =''|除非=''| sync ='false''使用解析器'org.springframework.cache.interceptor.SimpleCacheResolver@30a9fd0'。每个缓存操作应至少提供一个缓存。

我一直在问谷歌先生几天但却找不到合适的解决方案。我希望有人能在这里帮助我。对不起,如果我的问题不清楚或遗漏,因为这是我第一次在这里发帖。谢谢!

2 个答案:

答案 0 :(得分:0)

对要缓存的方法使用@CachedResult

在您的主要课程中使用@EnableCaching

示例代码: Main

@SpringBootApplication
@EnableCaching
@RestController
public class SpringBootCacheApplication {

    @Autowired
    SomeBean someBean;

    @RequestMapping(value = "/cached/{key}")
    public int getCachedMethod(@PathVariable("key") String key) {
        System.out.println("Got key as " + key);
        return someBean.someCachedResult(key);
    }

    public static void main(String[] args) {
        SpringApplication.run(SpringBootCacheApplication.class, args);
    }
}
我希望缓存的

SomeBean类containsig方法

@Component
public class SomeBean {

    @CacheResult
    public int someCachedResult(String key) {
        System.out.println("Generating random number");
        int num = new Random().nextInt(200);
        return num;
    }

}

someCachedResult方法中,我总是返回一些随机值。自缓存以来,您只能在第一次获得随机值。

此处SomeBean应与您的CachingUserRepository类相对应。

答案 1 :(得分:0)

我假设您已经设置了所需的配置,并且您发布的堆栈跟踪是问题所在。所以让我们挖掘它。

我看到两个问题:

  1.   

    j ava.lang.IllegalStateException:无法解析缓存,每个缓存操作至少应提供一个缓存

    解决方案:每当您想要缓存数据或逐出数据时,必须提供缓存的名称,我在代码中没有看到。

    应该定义

    @Cacheable's cacheNames or value以使缓存正常工作。

    示例@Cacheable(value = "usersCache")

  2. 正确的缓存密钥

    由于缓存适用于key-value对,因此您应该提供适当的缓存密钥。如果您没有提供缓存密钥,那么默认情况下,默认密钥生成策略会创建一个SimpleKey,其中包含调用该方法的所有参数。

  3. 建议:您应手动提供缓存密钥。

    示例:

    @Cacheable(value = "usersCache", key = "#username")
    User findByUsername(String username);
    

    注意:请确保用户名是唯一的,因为缓存密钥必须是唯一的。

    您可以阅读更多Spring cache annotations: some tips & tricks