Spring JPA原生查询使用Projection报ConverterNotFoundException问题
你遇到的这个ConverterNotFoundException是Spring Data JPA处理原生查询Projection时的典型问题,我来帮你梳理几个关键排查点和修复方案:
1. 确认Projection接口定义规范
首先,IdsOnly必须是一个接口(不能是普通类),并且接口中的getter方法要和查询返回的字段名严格匹配,或者通过@Value显式指定映射关系。举个例子:
如果你要查询id和user_id两个字段,接口应该这么写:
public interface IdsOnly { // 对应查询结果中的id字段 Long getId(); // 用@Value指定映射到原生查询的user_id字段 @Value("#{target.user_id}") String getUserId(); }
注意:如果你的数据库字段是下划线命名,接口用驼峰命名,Spring Data默认会自动转换,但字段名完全不匹配时,一定要用
@Value绑定到target(查询结果行对象)的对应字段。
2. 检查原生查询的字段别名
确保原生SQL返回的字段名(或别名)和Projection接口的getter完全对应。比如你的Projection是getId()和getUsername(),查询语句应该是:
SELECT id, username FROM your_table WHERE ...
如果原数据库字段是user_name,要给它取别名匹配getter:
SELECT id, user_name AS username FROM your_table WHERE ...
3. 确认@Query注解配置正确
在Repository方法上,必须指定nativeQuery=true,并且返回类型是你的Projection接口:
@Repository public interface YourRepository extends JpaRepository<YourEntity, Long> { @Query(value = "SELECT id, username FROM your_table WHERE status = ?1", nativeQuery = true) List<IdsOnly> findIdsByStatus(String status); }
4. 备选方案:Constructor Projection
如果上述方法都没解决,可以试试构造器投影的方式:
- 先创建一个普通DTO类,带对应字段的构造器:
public class IdsOnlyDto { private Long id; private String username; public IdsOnlyDto(Long id, String username) { this.id = id; this.username = username; } // getter方法可选,按需添加 public Long getId() { return id; } public String getUsername() { return username; } }
- 然后用JPQL查询(不能用nativeQuery=true)调用构造器:
@Query(value = "SELECT new com.example.IdsOnlyDto(id, username) FROM YourEntity WHERE status = ?1") List<IdsOnlyDto> findIdsByStatus(String status);
这种方式跳过Spring的类型转换,直接通过构造器实例化DTO,适配性更强。
5. 排查版本兼容性
如果你的Spring Data JPA版本较旧,可能存在原生查询Projection的兼容性bug,建议升级到2.7.x及以上的稳定版本,很多早期的转换问题在新版本中已经修复。
大部分情况下,问题都出在Projection接口与查询字段的映射不匹配上,先从这一点排查效率最高。
内容的提问来源于stack exchange,提问作者nonzaprej

