Spring Cache中用方法返回值设缓存键遇EL1007E异常的解决
问题根源:@Cacheable的执行顺序限制
你遇到的问题本质是Spring Cache注解的执行时机差异:
@Cacheable的key属性是在方法执行前解析的——Spring需要先根据key判断缓存里有没有对应数据,决定要不要执行方法。这时候方法还没运行,#result自然是null,所以访问#result.name就会抛出找不到属性的异常。- 而
unless属性是在方法执行完成后才会解析的——这时候方法已经返回了结果,#result指向实际的Person对象,所以能正常访问它的name属性。
解决方案:根据需求选择合适的缓存方式
1. 每次执行方法后用返回值name更新缓存
可以改用@CachePut注解,它的逻辑是先执行方法,再用方法结果生成key并存入缓存,这时候#result已经存在,能正常用于key的生成:
@CachePut(value = "Cache", key = "#result.name", unless="#result.name == 'Foo'") public Person getById(String id){ // 你的数据库查询逻辑 }
注意:@CachePut不会检查缓存,每次调用都会执行方法,适合需要确保缓存与数据源同步的场景。
2. 先通过name查询缓存,不存在再执行方法
如果业务允许,把方法参数改为name,直接用@Cacheable即可:
@Cacheable(value = "Cache", key = "#name", unless="#result.name == 'Foo'") public Person getByName(String name){ // 根据name查询数据库的逻辑 }
如果必须通过id查询,可以在getById方法中先查数据库得到Person,再调用getByName来复用缓存逻辑。
3. 手动控制缓存(最灵活)
如果以上注解方式不符合业务逻辑,直接用CacheManager手动操作缓存,完全掌握缓存时机和key生成:
@Autowired private CacheManager cacheManager; public Person getById(String id){ // 从数据库查询Person Person person = yourPersonRepository.findById(id).orElse(null); if(person != null && !"Foo".equals(person.getName())){ // 获取指定缓存 Cache cache = cacheManager.getCache("Cache"); // 以name为key存入缓存 cache.put(person.getName(), person); } return person; }
内容的提问来源于stack exchange,提问作者Iti Gupta
相关产品推荐
相关产品推荐

