SpringBoot + MyBatis-Plus 使用 listObjs 报 ClassCastException 的原因与解决办法
在项目中我们经常会遇到这种需求:
根据一组 ID 查询数据库,并返回指定字段列表。
我在写代码的时候,遇到了一个典型的坑,分享出来给大家。
一、问题背景
我的代码是这样写的(查询项目表的负责人信息):
@PostMapping("/getOwnerInfoList")
public Result getOwnerInfoList(@RequestBody List<Integer> pcIds) {
List<Map<String, Object>> result = pmPcService.listObjs(
new LambdaQueryWrapper<PmPc>()
.select(PmPc::getPcId, PmPc::getOwnerUserId, PmPc::getDocumentCode)
.in(PmPc::getPcId, pcIds),
pc -> {
PmPc p = (PmPc) pc; // 👈 报错点
Map<String, Object> map = new HashMap<>();
map.put("pcId", p.getPcId());
map.put("ownerUserId", p.getOwnerUserId());
map.put("documentCode", p.getDocumentCode());
return map;
}
);
return R.ok(result);
}
结果运行时直接报错:
java.lang.ClassCastException: java.lang.Integer cannot be cast to com.kakarote.pm.entity.PO.PmPc
二、原因分析
问题的关键在于 listObjs
方法的返回值。
listObjs
的官方说明是:
查询并返回对象集合,默认只会返回查询结果的 第一列。
也就是说,如果你 select
了三列(pcId, ownerUserId, documentCode
),listObjs
默认只返回第一列 pcId
。
所以 pc
其实是 Integer
,你强转成 PmPc
就会报 ClassCastException
。
如果你写了 resultHandler 回调,查询多列时返回的是 Object[]
,而不是实体对象。
三、正确的解决方案
方式一:直接用 list
最简单的方式就是不用 listObjs
,而是用 list
,这样返回的就是实体对象
List<PmPc> list = pmPcService.list(new LambdaQueryWrapper<PmPc>().select(PmPc::getPcId, PmPc::getOwnerUserId, PmPc::getDocumentCode).in(PmPc::getPcId, pcIds)
);List<Map<String, Object>> result = list.stream().map(p -> {Map<String, Object> map = new HashMap<>();map.put("pcId", p.getPcId());map.put("ownerUserId", p.getOwnerUserId());map.put("documentCode", p.getDocumentCode());return map;
}).collect(Collectors.toList());return R.ok(result);
方式二:继续用 listObjs
如果一定要用 listObjs
,正确写法如下:
List<Map<String, Object>> result = pmPcService.listObjs(new LambdaQueryWrapper<PmPc>().select(PmPc::getPcId, PmPc::getOwnerUserId, PmPc::getDocumentCode).in(PmPc::getPcId, pcIds),obj -> {Object[] arr = (Object[]) obj; // listObjs 查询多列时返回 Object[]Map<String, Object> map = new HashMap<>();map.put("pcId", arr[0]);map.put("ownerUserId", arr[1]);map.put("documentCode", arr[2]);return map;}
);
四、总结
listObjs
默认只返回第一列,别以为它能直接返回实体。如果你需要实体对象,用
list
更直观。如果你需要自定义对象,用
listObjs
+Object[]
来处理。
💡 推荐:
如果业务中经常要查多列 → 用 list
;
如果只查单列(比如只查 id
列表) → 用 listObjs
。