Spring JPA原生查询后无法获取数据列表,返回结果转Entrant类报错
错误原因
该报错是因为Spring Data JPA的原生查询默认没有内置转换器,无法直接将查询返回的TupleBackedMap结构自动映射到你自定义的非@EntityPOJO类Entrant上。
可用解决方法
方法1:使用JPA官方SqlResultSetMapping映射(兼容性最优)
这是JPA规范原生支持的映射方案,步骤如下:
- 在任意已有的
@Entity实体类(如Event、User类都可以)上添加结果集映射注解:
@SqlResultSetMapping( name = "EntrantMapping", classes = @ConstructorResult( targetClass = Entrant.class, columns = { @ColumnResult(name = "firstname", type = String.class), @ColumnResult(name = "surname", type = String.class), @ColumnResult(name = "handicap", type = Double.class), @ColumnResult(name = "score", type = Integer.class) } ) ) @Entity public class Event { // 原有Event实体的代码保持不变 }
- 修改Repository的
@Query注解,指定刚才定义的映射:
@Query(value = "SELECT member.firstname, member.surname, member.handicap, entrants.score FROM member INNER JOIN entrants ON member.userid=entrants.member_id WHERE entrants.event_id=:eventid", nativeQuery = true, resultSetMapping = "EntrantMapping") List<Entrant> getEntrantDetails(long eventid);
方法2:使用接口投影(实现最简单)
如果不需要对返回的参赛人员信息做修改,可以直接把Entrant改成接口形式的投影,Spring Data会自动完成映射:
public interface EntrantProjection { String getFirstname(); String getSurname(); Double getHandicap(); Integer getScore(); }
然后直接把Repository方法的返回值改成List<EntrantProjection>即可,不需要额外加其他注解。
方法3:手动转换结果集(灵活度最高)
先让Repository返回Map结构的结果集,在服务层手动转换为Entrant对象:
- 修改Repository方法:
@Query(value = "SELECT member.firstname, member.surname, member.handicap, entrants.score FROM member INNER JOIN entrants ON member.userid=entrants.member_id WHERE entrants.event_id=:eventid", nativeQuery = true) List<Map<String, Object>> getEntrantDetails(long eventid);
- 修改服务层代码做类型转换:
public List<Entrant> getEntrantDetails(long id){ List<Map<String, Object>> rawResult = eventRepository.getEntrantDetails(id); return rawResult.stream().map(item -> { Entrant entrant = new Entrant(); entrant.setFirstname((String) item.get("firstname")); entrant.setSurname((String) item.get("surname")); entrant.setHandicap(((Number) item.get("handicap")).doubleValue()); entrant.setScore((Integer) item.get("score")); return entrant; }).collect(Collectors.toList()); }
注意事项
- 确保查询返回的字段名和Entrant类的字段名完全匹配,如有不一致可以在SQL中用
AS别名调整 - 注意字段类型匹配,数值类字段如果数据库返回为BigDecimal类型,需要先转为Number再转成对应类型避免类型转换异常
内容的提问来源于stack exchange,提问作者James Smith
相关产品推荐
相关产品推荐

