如何添加JPA将忽略的参数?缓存实现遇NoSuchElementException
解决Spring Data JPA中添加缓存控制参数的问题
你遇到的异常是因为Spring Data JPA会自动将方法参数解析为JPQL查询参数,但你的方法名生成的查询里并没有对应这个参数的占位符,导致参数绑定失败。要添加一个仅用于缓存控制、被JPA忽略的参数,有以下两种可靠方案:
方案一:显式使用@Query定义查询语句
通过@Query直接编写JPQL,让JPA只处理查询语句中声明的参数,方法里的额外参数仅被Spring Cache使用:
public interface SomethingRepository extends PagingAndSortingRepository<Something, String> { @Cacheable(value = "listOfSomething", cacheManager = "somethingCacheManager", unless = "#cacheResults == false") @Query("SELECT s FROM Something s ORDER BY s.name ASC") List<Something> findAllOrderByNameAsc(boolean cacheResults); }
@Query明确指定了查询逻辑,JPA不会尝试将cacheResults作为查询参数绑定,只会处理JPQL里的参数(这里没有查询参数)。unless的作用是满足条件时不缓存,你可以根据实际需求调整表达式:比如#cacheResults == true表示当传入true时不缓存,#cacheResults == false表示传入false时不缓存。
方案二:使用@Param注解并确保JPQL不引用该参数
如果不想写完整的JPQL,也可以给缓存参数加上@Param,但要确保方法名生成的查询不会用到它(不过这种方式不如显式@Query清晰,推荐第一种):
public interface SomethingRepository extends PagingAndSortingRepository<Something, String> { @Cacheable(value = "listOfSomething", cacheManager = "somethingCacheManager", unless = "#cacheResults == true") @Param("cacheResults") List<Something> findAllOrderByNameAsc(boolean cacheResults); }
这种方式需要确保Spring Data JPA生成的JPQL中没有对应cacheResults的条件,由于方法名是findAllOrderByNameAsc,本身不带查询条件,理论上也可以生效,但显式@Query的方式更稳妥,避免后续方法名修改带来的问题。
关键原理
Spring Data JPA的方法名解析机制会把所有方法参数视为查询参数,尝试绑定到生成的JPQL中。当JPQL里没有对应参数的占位符时,就会抛出参数绑定异常。通过显式@Query定义查询,可以完全控制哪些参数参与JPQL绑定,哪些仅用于缓存或其他切面逻辑。
内容的提问来源于stack exchange,提问作者Starkom
相关产品推荐
相关产品推荐

