Spring Data JPA原生查询映射自定义DTO报No converter found错误如何处理
错误产生原因
- Spring Data JPA 原生查询默认返回
TupleBackedMap(元组映射的Map结构)或Object[]类型的结果集,你定义的UsersXCountry是普通POJO类,没有配置对应的字段映射规则,JPA没有内置转换器可以直接把查询结果自动映射到自定义普通类实例。 - 你的原生查询返回的列没有匹配DTO属性名:查询返回的列分别是无别名的
count('1')、下划线命名的country_code,和DTO中驼峰命名的numUsers、countryCode属性无法自动对应,进一步导致映射失败。
解决方案
下面是3种常用的可行方案:
方案1:使用接口投影(最简方案)
把UsersXCountry改为接口形式定义投影,JPA会自动生成代理类完成映射:
// 改为接口,定义和返回字段对应的getter方法 public interface UsersXCountry { Integer getNumUsers(); String getCountryCode(); }
修改Repository中的查询语句,给查询列加和getter对应的别名:
@Query(value = "select count('1') as numUsers, country_code as countryCode from t_user group by country_code",nativeQuery = true) List<UsersXCountry> usersXCountry();
方案2:使用结果集映射注解适配POJO
如果要保留UsersXCountry作为普通类的写法,先给类加全参构造方法:
public class UsersXCountry { Integer numUsers; String countryCode; // 手动加或者用Lombok的@AllArgsConstructor生成 public UsersXCountry(Integer numUsers, String countryCode) { this.numUsers = numUsers; this.countryCode = countryCode; } // 按需加getter、setter }
在项目任意被JPA扫描的实体类上或者当前DTO类上添加结果集映射配置:
@SqlResultSetMapping( name = "UsersXCountryMapping", classes = @ConstructorResult( targetClass = UsersXCountry.class, columns = { @ColumnResult(name = "numUsers", type = Integer.class), @ColumnResult(name = "countryCode", type = String.class) } ) )
修改Repository的查询注解,指定映射规则,同时给查询列加别名:
@Query(value = "select count('1') as numUsers, country_code as countryCode from t_user group by country_code", nativeQuery = true, resultSetMapping = "UsersXCountryMapping") List<UsersXCountry> usersXCountry();
方案3:手动转换结果集
无需修改查询和DTO配置,先接收原始结果集再手动转换:
// Repository层先返回原始Object数组 @Query(value = "select count('1'), country_code from t_user group by country_code",nativeQuery = true) List<Object[]> usersXCountryRaw();
在业务层手动转换:
List<Object[]> rawList = userRepository.usersXCountryRaw(); List<UsersXCountry> result = rawList.stream().map(arr -> new UsersXCountry(((Number)arr[0]).intValue(), (String)arr[1]) ).toList();
内容的提问来源于stack exchange,提问作者Nunyet Calçada
相关产品推荐
相关产品推荐

