【问题标题】:After @CachePut findAll() doesn't give result from cache在@CachePut findAll() 没有从缓存中给出结果之后
【发布时间】:2020-05-07 11:22:22
【问题描述】:

我正在学习 Spring Boot 缓存以将这个概念应用到我们组织的项目中,并且我制作了一个名为employee cache 的示例项目。我的控制器和服务组件中有四种方法 insert、update、get 和 getAll。对于 insert 和 get @Cacheable 工作正常。现在我第一次调用getAllEmployee() 然后它从数据库中获取数据。之后,我尝试使用@CachePut 进行更新,它会更新数据库中的值,然后我再次调用getAllEmployee(),然后它没有从缓存中返回更新的值。对于@CachePut,我还参考了documentation。我还参考了其他一些文档,例如thisthis,但我没有解决我的问题。另外,当我打电话时,不会引发错误。
我尝试的是
这是我来自EmplyeeController.java的两个API

@PostMapping(value = "/updateSalary")
private Boolean updateSalary(@RequestParam int salary, @RequestParam Integer id) {
    return empService.updateSalary(salary, id);
}

@GetMapping(value = "/getAllEmployee")
private Object getAllEmployee() {
    List<EmployeeMapping> empList = empService.getAllEmployee();
    return !empList.isEmpty() ? empList : "Something went wrong";
}

这是我来自EmployeeService.java 的两种方法。我应用了不同的键来更新方法,但没有用。我的getAll() 方法没有参数,所以我尝试了here 的所有无参数方法的关键技术,然后我也没有得到任何结果。

@CachePut(key = "#root.method.name")
public Boolean updateSalary(int salary, int id) {
    System.err.println("updateSalary method is calling in service");
    if (empRepo.salary(salary, id) != 0) {
        return true;
    }
    return false;
}

@Cacheable(key = "#root.method.name")
public List<EmployeeMapping> getAllEmployee() {
    return empRepo.findAllEmployee();
}

这是我来自EmployeeRepository.java 的两种方法。我在EmployeeMetaModel.javaEmployeeMapping.java 中使用了@SqlResultSetMappings@NamedNativeQueries,但是EmployeeMetaModel.java 中的本机查询没有错误,因为它是从数据库中给出结果的。

@Transactional
@Modifying
@Query("update employee_cache e set e.salary = ?1 where e.id = ?2")
int salary(int salary, int id);

@Query(name = "EmployeeListQuery", nativeQuery = true)
List<EmployeeMapping> findAllEmployee();

请帮助我摆脱这个问题,我只需要在调用 updateSalary() 之后使用 getAllEmployee() 从缓存中更新值。

【问题讨论】:

    标签: java spring-boot spring-cache


    【解决方案1】:

    您通过注释定义缓存的方式存在问题。您的 @CachePut@Cacheable 不使用相同的缓存键。您实际上应该拥有的是这样的:

    @CachePut(value = "employees", key = "T(org.springframework.cache.interceptor.SimpleKey).EMPTY")
    public List<EmployeeMapping> updateSalary(int salary, int id) {
        // update salary and return the list of employees
    }
    
    @Cacheable(value = "employees")
    public List<EmployeeMapping> getAllEmployee() {
        // return the list of employees
    }
    

    这里@CachePut@Cacheable拥有相同的缓存键。d 现在,当你调用updateSalary()方法时,@CachePut将替换键“employees”的现有缓存值 ,以及方法的结果,即具有更新工资的员工列表。

    【讨论】:

    • 感谢您的宝贵回答@Igor。我尝试了您的解决方案,但根据我们必须遵循 SPEL 进行密钥声明的规则,因此我们必须添加 #employees 而不仅仅是 employees。否则,它将给org.springframework.expression.spel.SpelEvaluationException
    • 另外,我尝试使用#employees,但它不起作用,我尝试@CacheConfig(cacheNames = "employee")@CachePut(value = "employee", key = "#employees") 它也不起作用。
    • @DeepDalsania 我已经更新了我的答案。 @CachePut 中键的 SpEL 表达式应与 Spring 用于缓存 @Cacheable 注释方法(即 getAllEmployee)的结果的键值匹配
    • 我试过你的更新答案@Igor。首先我打电话给getAllEmployee()。它通过触发查询给出了结果。第二我打电话给updateSalary()。它更新触发查询的数据。第三,我再次调用了getAllEmployee(),它给了java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.util.List at com.spring.cache.service.EmployeeService$$EnhancerBySpringCGLIB$$90d3116e.getAllEmployee(&lt;generated&gt;) 异常,我将我的服务getAllEmployee() 调用到控制器。
    • 您似乎没有更新updateSalary,它仍然返回BooleanupdateSalary 应该返回与 `getAllEmployee` 相同类型的结果,即 @CachePut 正常工作的 List。这个结果是@CachePut 用来替换缓存中现有值的值。如果您确实需要 updateSalary 方法的布尔结果,那么您必须使用 org.springframework.cache.CacheManager 而不是 @CachePut 注释更新 updateSalary 内的缓存。
    猜你喜欢
    • 1970-01-01
    • 2019-12-09
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 2018-11-30
    • 2014-03-12
    • 1970-01-01
    相关资源
    最近更新 更多