项目场景:
根据特定条件查询数据,将查询结果使用stream流过滤后,使用过滤后的数据作为条件执行删除操作
问题描述
使用mybatis-plus的lamb表达式进行查询,然后对查询结果使用stream流过滤,将过滤后的结果用做删除条件,报空指针错误
示例代码:
List<String> xhList = emptyList.stream().map(BookTemp::getXh).collect(Collectors.toList());
LambdaQueryWrapper<Book> queryIds = new LambdaQueryWrapper<>();
queryIds.select(Book::getId)
.select(Book::getXh)
.in(Book::getXh, xhList);
List<Book> trsList = bookRecordMapper.selectList(queryIds);
if (CollectionUtil.isNotEmpty(trsList)) {
// 删除表里的数据
List<String> idList = trsList.stream().map(Book::getId).collect(Collectors.toList());
if (CollectionUtil.isNotEmpty(idList)){
bookMapper.deleteBatchIds(idList);
}
}
原因分析:
注意看代码一,lamb查询语句中,使用了两个select
// 代码段一
LambdaQueryWrapper queryIds = new LambdaQueryWrapper<>();
queryIds.select(Book::getId)
.select(Book::getXh)
.in(Book::getXh, xhList);
// 代码段二
List idList = trsList.stream().map(Book::getId).collect(Collectors.toList());
// 代码段三
if (CollectionUtil.isNotEmpty(idList)){
bookMapper.deleteBatchIds(idList);
}
在代码段一中,错误的使用了两个select,通过debug查询,mybatis-plus只查询了“xh”字段,没有查询“id”字段,查询结果不为空,xh字段有值,其他字段无值。
在代码段二中,使用stream流取出了 “id”字段,注意,idList有长度,但没有值。
在代码段三中,优于idList有长度,所以继续执行删除操作,但 idList 却没有值,所以报错
解决方案:
// 使用正确的mybatis-plus查询语句 List<String> xhList = emptyList.stream().map(BookTemp::getXh).collect(Collectors.toList()); LambdaQueryWrapper<Book> queryIds = new LambdaQueryWrapper<>(); queryIds.select(Book::getId,Book::getXh) .in(Book::getXh, xhList);
使用正确的mybatis-plus查询语句,只使用一个 select子句,然后将多个查询字段一起声明,则在查到数据不为空的情况下,id字段的值必然存在,在代码二的时候,可以正确取到 id的值
扩展
List<String> idList = trsList.stream().map(Book::getId).collect(Collectors.toList());
在使用stream流中的map取值时,如果无法确定所取的值一定为空,可先过滤值为空的情况,这样就不会出现,结果集合有长度,但却没有值的情况,示例:
先判断 “id”值为空,再取值,这样取到的结果,就不会出现 idList有长度,但没有值的情况
List<String> idList = trsList.stream()
.filter(e -> StringUtils.isNotBlank(e.getId()))
.map(Book::getId)
.collect(Collectors.toList());