LambdaQueryWrapper
爆出空指针异常的坑点分析来看一段常见的 MyBatis-Plus 查询写法,是否存在问题?
Page<VideoInfoVo> videoInfoVosPage = videoMapper.selectPage(page, new LambdaQueryWrapper<VideoInfoVo>()
.eq(videoAdtReq.getUserId() != null, VideoInfoVo::getUserId, videoAdtReq.getUserId())
.ge(videoAdtReq.getStartTime() != null, VideoInfoVo::getUpdateTime, videoAdtReq.getStartTime().atStartOfDay())
.le(videoAdtReq.getEndTime() != null, VideoInfoVo::getUpdateTime, videoAdtReq.getEndTime().atTime(LocalTime.MAX))
);
.ge(videoAdtReq.getStartTime() != null, VideoInfoVo::getUpdateTime, videoAdtReq.getStartTime().atStartOfDay())
.le(videoAdtReq.getEndTime() != null, VideoInfoVo::getUpdateTime, videoAdtReq.getEndTime().atTime(LocalTime.MAX))
表面上看已经做了非空判断,似乎没有问题,但实际上,这样写仍然可能爆出 NullPointerException
。
Java 会在调用方法前,先对所有参数进行求值,然后再把这些值传给方法体。
所以即使你写了:
videoAdtReq.getStartTime() != null
Java 仍然会执行:
videoAdtReq.getStartTime().atStartOfDay()
如果 getStartTime()
返回的是 null
,那 .atStartOfDay()
立即爆 NPE
!
LocalDateTime start = null;
LocalDateTime end = null;
if (videoAdtReq.getStartTime() != null) {
start = videoAdtReq.getStartTime().atStartOfDay();
}
if (videoAdtReq.getEndTime() != null) {
end = videoAdtReq.getEndTime().atTime(LocalTime.MAX);
}
Page<VideoInfoVo> videoInfoVosPage = videoMapper.selectPage(page, new LambdaQueryWrapper<VideoInfoVo>()
.eq(videoAdtReq.getUserId() != null, VideoInfoVo::getUserId, videoAdtReq.getUserId())
.ge(start != null, VideoInfoVo::getUpdateTime, start)
.le(end != null, VideoInfoVo::getUpdateTime, end)
);
写法 | 是否安全 | 原因 |
---|---|---|
.eq(cond, field, value) |
✅ 安全 | 不涉及链式 null 调用 |
.ge(cond, field, value.atStartOfDay()) |
❌ 危险 | 即使 cond == false ,value.atStartOfDay() 已执行 |
null
的链式操作都要提前拆解;.ge()
、.le()
、.like()
等条件方法内部写链式 null 调用;