Spring Data JPA中结合Specification与投影的查询实现报错求助
Spring Data JPA中结合Specification与投影的查询实现报错求助
看起来你遇到的是Spring Data JPA方法命名规则和Specification、投影结合时的适配问题,我来帮你梳理下问题根源和解决方案:
问题原因分析
你写的两个findAllBy方法触发报错,核心问题出在Spring Data JPA的命名查询解析逻辑上:
- 当方法名包含
By关键字时,框架默认会认为你要根据By后面的实体属性生成查询(比如findAllByUserName会解析为按userName字段查询)。但你的方法里By后面没有跟任何属性名,框架就会生成一个不需要参数的查询模板,可你又传入了Specification参数,自然就出现了“参数数量不匹配”的错误。 - 另外第二个方法里的
Specification<?>泛型声明也不准确,应该明确指定为Specification<User>,和你的实体类型保持一致,避免类型匹配问题。
修正后的解决方案
把那两个报错的方法替换成基于findAll的重载版本(Spring Data JPA 3.x+已经支持在findAll中同时传入Specification和投影类型),修改后的Repository代码如下:
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> { User findUserByUserNameIgnoreCase(String username); <T> T findById(Long id, Class<T> type); // works <T> List<T> findAllBy(Class<T> type); // works // 修正:用findAll替代findAllBy,同时指定正确的Specification泛型 <T> List<T> findAll(Specification<User> specification, Class<T> type); List<UserInfoProjection> findAll(Specification<User> specification); interface Specs { static Specification<User> id(Long id) { return (root, query, builder) -> builder.equal(root.get("id"), id); } } }
对应的方法调用也需要同步改为使用findAll:
List<UserInfoProjection> up = userRepository.findAll(UserRepository.Specs.id(userID)); List<UserInfoProjection> pp = userRepository.findAll(UserRepository.Specs.id(userID), UserInfoProjection.class);
补充说明
这样修改后,框架就能正确识别:你是要通过Specification定义查询条件,同时用指定的投影类型返回结果,完全符合Spring Data JPA 3.x+的动态投影+Specification特性设计。
备注:内容来源于stack exchange,提问作者code_copy_paste
相关产品推荐
相关产品推荐

