ElasticSearch SQL查询结果转EmployeeDto遇ClassCastException求助
解决Elasticsearch SQL查询结果转EmployeeDto的类型转换问题
错误原因分析
你遇到的ClassCastException是因为Elasticsearch返回的rows是嵌套数组结构:外层数组对应多行记录,每个内层数组对应一行的字段值(比如[12345, 30000])。你直接把rows强转为ArrayList<EmployeeDto>,但内层元素是ArrayList而非EmployeeDto,必然触发类型转换错误。
第一步:修正EmployeeDto定义
Java属性规范为小驼峰命名,需与JSON返回的字段名通过@JsonProperty明确映射,同时移除无用的拷贝构造函数:
@Data public class EmployeeDto { @JsonProperty("EmployeeId") private Long employeeId; @JsonProperty("Salary") private Long salary; }
方案一:手动映射(固定字段场景)
直接从嵌套数组中取值并手动赋值给DTO,适合字段固定的业务场景:
Response response = restClient.performRequest(request); InputStream is = response.getEntity().getContent(); ObjectMapper mapper = new ObjectMapper(); // 解析整个响应为Map结构 Map<String, Object> responseMap = mapper.readValue(is, Map.class); // 取出rows:外层是List,每个元素为存储字段值的内层List List<List<Object>> rows = (List<List<Object>>) responseMap.get("rows"); // 取出唯一的一行记录并赋值 if (!rows.isEmpty()) { List<Object> row = rows.get(0); EmployeeDto dto = new EmployeeDto(); // 按columns的顺序赋值:第一个元素对应EmployeeId,第二个对应Salary dto.setEmployeeId(Long.valueOf(row.get(0).toString())); dto.setSalary(Long.valueOf(row.get(1).toString())); // 后续业务逻辑使用dto Long salaryValue = dto.getSalary(); }
方案二:结合columns动态映射(字段可变场景)
如果后续字段可能变化,可利用返回的columns信息动态匹配字段与DTO属性:
Response response = restClient.performRequest(request); InputStream is = response.getEntity().getContent(); ObjectMapper mapper = new ObjectMapper(); // 解析响应为Map结构 Map<String, Object> responseMap = mapper.readValue(is, Map.class); // 获取字段定义列表和数据行列表 List<Map<String, String>> columns = (List<Map<String, String>>) responseMap.get("columns"); List<List<Object>> rows = (List<List<Object>>) responseMap.get("rows"); if (!rows.isEmpty()) { List<Object> row = rows.get(0); EmployeeDto dto = new EmployeeDto(); // 遍历字段定义,将对应位置的值赋值给DTO for (int i = 0; i < columns.size(); i++) { String fieldName = columns.get(i).get("name"); Object value = row.get(i); switch (fieldName) { case "EmployeeId": dto.setEmployeeId(Long.valueOf(value.toString())); break; case "Salary": dto.setSalary(Long.valueOf(value.toString())); break; // 后续新增字段可在此补充 } } // 后续业务逻辑使用dto Long salaryValue = dto.getSalary(); }
注意事项
- Elasticsearch SQL查询返回的
rows字段顺序与columns顺序完全一致,需严格对应 - 数字类型建议先转为字符串再强转,避免潜在的类型不匹配问题
内容的提问来源于stack exchange,提问作者Keerthana Hemachandran
相关产品推荐
相关产品推荐

