Spring Boot MyBatis-Plus处理日期范围查询代码报错分析与修复
以下spring boot + mybatis-plus代码报错:
/**
* 获取资金信息列表
*/
public List<CapitalInfoVO> queryList(@NotNull CapitalInfoQueryDTO queryDTO) {
LambdaQueryWrapper<CapitalInfo > queryWrapper = new LambdaQueryWrapper<>();
// 构造查询条件
queryWrapper
// 模糊查询 - 资金序号
.like(StringUtils.hasText(queryDTO.getCapitalNo()), CapitalInfo::getCapitalNo, queryDTO.getCapitalNo())
// 模糊查询 - 资金名称
.like(StringUtils.hasText(queryDTO.getCapitalName()), CapitalInfo::getCapitalName, queryDTO.getCapitalName())
// 精确查询 - 资金类别
.eq(StringUtils.hasText(queryDTO.getCapitalType()), CapitalInfo::getCapitalType, queryDTO.getCapitalType())
// 精确查询 - 指标类别
.eq(StringUtils.hasText(queryDTO.getCapitalIndexType()), CapitalInfo::getCapitalIndexType, queryDTO.getCapitalIndexType())
// 模糊查询 - 资金账户
.like(StringUtils.hasText(queryDTO.getCapitalAccount()), CapitalInfo::getCapitalAccount, queryDTO.getCapitalAccount())
// 精确查询 - 资金来源
.eq(StringUtils.hasText(queryDTO.getCapitalSource()), CapitalInfo::getCapitalSource, queryDTO.getCapitalSource())
// 精确查询 - 指标来源
.eq(StringUtils.hasText(queryDTO.getCapitalIndexSource()), CapitalInfo::getCapitalIndexSource, queryDTO.getCapitalIndexSource())
// 精确查询 - 资金年份
.eq(queryDTO.getCapitalYear() != null, CapitalInfo::getCapitalYear, queryDTO.getCapitalYear())
// 精确查询 - 资金状态
.eq(queryDTO.getCapitalState() != null, CapitalInfo::getCapitalState, queryDTO.getCapitalState())
// 模糊查询 - 备注信息
.like(StringUtils.hasText(queryDTO.getRemark()), CapitalInfo::getRemark, queryDTO.getRemark())
// between - 创建日期
.between(
queryDTO.getCreateDate().size() == 2,
CapitalInfo::getCreateTime,
DateUtils.parseDateTimeRange(queryDTO.getCreateDate()).get(0),
DateUtils.parseDateTimeRange(queryDTO.getCreateDate()).get(1)
)
// 倒序排序 - 资金年份
.orderByDesc(CapitalInfo::getCapitalYear)
// 倒序排序 - 主键id
.orderByDesc(CapitalInfo::getId);
List<CapitalInfo> capitalInfos = capitalInfoMapper.selectList(queryWrapper);
// List<CapitalInfo> -> List<CapitalInfoVO>
return capitalInfos.stream()
.map(capitalInfo -> {
CapitalInfoVO capitalInfoVO = new CapitalInfoVO();
BeanUtils.copyProperties(capitalInfo, capitalInfoVO);
return capitalInfoVO;
})
.collect(Collectors.toList());
}
报错:
java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64) ~[na:na]
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70) ~[na:na]
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:266) ~[na:na]
at java.base/java.util.Objects.checkIndex(Objects.java:359) ~[na:na]
at java.base/java.util.ArrayList.get(ArrayList.java:427) ~[na:na]
at com.weiyu.service.CapitalInfoService.queryList(CapitalInfoService.java:67) ~[classes/:na]
at com.weiyu.controller.CapitalInfoController.queryList(CapitalInfoController.java:53) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:355) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:58) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:720) ~[spring-aop-6.1.15.jar:6.1.15]
at com.weiyu.controller.CapitalInfoController$$SpringCGLIB$$0.queryList(<generated>) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:255) ~[spring-web-6.1.15.jar:6.1.15]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:188) ~[spring-web-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926) ~[spring-webmvc-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831) ~[spring-webmvc-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) ~[spring-webmvc-6.1.15.jar:6.1.15]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[tomcat-embed-core-10.1.33.jar:6.0]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.15.jar:6.1.15]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.33.jar:6.0]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.33.jar:10.1.33]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.1.15.jar:6.1.15]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.15.jar:6.1.15]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.1.15.jar:6.1.15]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.15.jar:6.1.15]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.1.15.jar:6.1.15]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.15.jar:6.1.15]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:397) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:905) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at java.base/java.lang.Thread.run(Thread.java:842) ~[na:na]
根据堆栈跟踪,错误发生在 CapitalInfoService.java 的第 67 行。查看您的代码,这个位置是:
java
.between(
queryDTO.getCreateDate().size() == 2,
CapitalInfo::getCreateTime,
DateUtils.parseDateTimeRange(queryDTO.getCreateDate()).get(0),
DateUtils.parseDateTimeRange(queryDTO.getCreateDate()).get(1)
)
错误 IndexOutOfBoundsException: Index 0 out of bounds for length 0 表示您尝试访问一个空列表的第一个元素。
问题分析:
-
当
queryDTO.getCreateDate()为null或空列表时,调用.size()会导致空指针异常,但这里显然不是这种情况,因为您已经检查了.size() == 2 -
更可能的问题是
DateUtils.parseDateTimeRange(queryDTO.getCreateDate())返回了一个空列表,即使传入的queryDTO.getCreateDate()不为空且有 2 个元素
解决方案:
修改您的代码,确保在访问列表元素之前先验证列表不为空:
java
public List<CapitalInfoVO> queryList(@NotNull CapitalInfoQueryDTO queryDTO) {
LambdaQueryWrapper<CapitalInfo> queryWrapper = new LambdaQueryWrapper<>();
// 构造查询条件
queryWrapper
// 模糊查询 - 资金序号
.like(StringUtils.hasText(queryDTO.getCapitalNo()), CapitalInfo::getCapitalNo, queryDTO.getCapitalNo())
// 模糊查询 - 资金名称
.like(StringUtils.hasText(queryDTO.getCapitalName()), CapitalInfo::getCapitalName, queryDTO.getCapitalName())
// 精确查询 - 资金类别
.eq(StringUtils.hasText(queryDTO.getCapitalType()), CapitalInfo::getCapitalType, queryDTO.getCapitalType())
// 精确查询 - 指标类别
.eq(StringUtils.hasText(queryDTO.getCapitalIndexType()), CapitalInfo::getCapitalIndexType, queryDTO.getCapitalIndexType())
// 模糊查询 - 资金账户
.like(StringUtils.hasText(queryDTO.getCapitalAccount()), CapitalInfo::getCapitalAccount, queryDTO.getCapitalAccount())
// 精确查询 - 资金来源
.eq(StringUtils.hasText(queryDTO.getCapitalSource()), CapitalInfo::getCapitalSource, queryDTO.getCapitalSource())
// 精确查询 - 指标来源
.eq(StringUtils.hasText(queryDTO.getCapitalIndexSource()), CapitalInfo::getCapitalIndexSource, queryDTO.getCapitalIndexSource())
// 精确查询 - 资金年份
.eq(queryDTO.getCapitalYear() != null, CapitalInfo::getCapitalYear, queryDTO.getCapitalYear())
// 精确查询 - 资金状态
.eq(queryDTO.getCapitalState() != null, CapitalInfo::getCapitalState, queryDTO.getCapitalState())
// 模糊查询 - 备注信息
.like(StringUtils.hasText(queryDTO.getRemark()), CapitalInfo::getRemark, queryDTO.getRemark())
// 倒序排序 - 资金年份
.orderByDesc(CapitalInfo::getCapitalYear)
// 倒序排序 - 主键id
.orderByDesc(CapitalInfo::getId);
// 处理日期范围查询 - 单独处理以避免空列表访问
if (queryDTO.getCreateDate() != null && queryDTO.getCreateDate().size() == 2) {
List<Date> dateRange = DateUtils.parseDateTimeRange(queryDTO.getCreateDate());
if (dateRange != null && dateRange.size() == 2) {
queryWrapper.between(CapitalInfo::getCreateTime, dateRange.get(0), dateRange.get(1));
} else {
// 可以记录日志或进行其他处理
log.warn("日期解析失败,将跳过日期范围查询条件");
}
}
List<CapitalInfo> capitalInfos = capitalInfoMapper.selectList(queryWrapper);
// List<CapitalInfo> -> List<CapitalInfoVO>
return capitalInfos.stream()
.map(capitalInfo -> {
CapitalInfoVO capitalInfoVO = new CapitalInfoVO();
BeanUtils.copyProperties(capitalInfo, capitalInfoVO);
return capitalInfoVO;
})
.collect(Collectors.toList());
}
替代方案(如果仍想保持链式调用):
java
// 在链式调用之前处理日期范围
Date startDate = null;
Date endDate = null;
if (queryDTO.getCreateDate() != null && queryDTO.getCreateDate().size() == 2) {
List<Date> dateRange = DateUtils.parseDateTimeRange(queryDTO.getCreateDate());
if (dateRange != null && dateRange.size() == 2) {
startDate = dateRange.get(0);
endDate = dateRange.get(1);
}
}
// 构造查询条件
queryWrapper
// ... 其他条件
.between(startDate != null && endDate != null,
CapitalInfo::getCreateTime, startDate, endDate)
// ... 排序条件
建议:
-
检查
DateUtils.parseDateTimeRange方法:这个方法可能在某些输入下返回空列表。您需要确保它正确处理输入并返回预期的结果。 -
添加日志记录:记录解析失败的情况,以便调试。
-
防御性编程:在处理可能返回空值的方法时,始终进行空值检查。
这样修改后,您的代码将更加健壮,不会因为 DateUtils.parseDateTimeRange 返回空列表而导致程序崩溃。
报错:
2026-01-14T12:02:43.607+08:00 ERROR 37936 --- [nio-8080-exec-1] c.w.exception.GlobalExceptionHandler : 异常错误: Cannot invoke "java.util.List.isEmpty()" because the return value of "com.weiyu.model.CapitalInfoQueryDTO.getCreateDate()" is null
java.lang.NullPointerException: Cannot invoke "java.util.List.isEmpty()" because the return value of "com.weiyu.model.CapitalInfoQueryDTO.getCreateDate()" is null
at com.weiyu.controller.CapitalInfoController.queryList(CapitalInfoController.java:46) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:355) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:58) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.15.jar:6.1.15]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:720) ~[spring-aop-6.1.15.jar:6.1.15]
at com.weiyu.controller.CapitalInfoController$$SpringCGLIB$$0.queryList(<generated>) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:255) ~[spring-web-6.1.15.jar:6.1.15]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:188) ~[spring-web-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926) ~[spring-webmvc-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831) ~[spring-webmvc-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.15.jar:6.1.15]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) ~[spring-webmvc-6.1.15.jar:6.1.15]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[tomcat-embed-core-10.1.33.jar:6.0]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.15.jar:6.1.15]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.33.jar:6.0]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.33.jar:10.1.33]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.1.15.jar:6.1.15]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.15.jar:6.1.15]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.1.15.jar:6.1.15]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.15.jar:6.1.15]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.1.15.jar:6.1.15]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.15.jar:6.1.15]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:397) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:905) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
at java.base/java.lang.Thread.run(Thread.java:842) ~[na:na]
根据错误信息,新的问题出现在 CapitalInfoController.java 的第46行,错误是 NullPointerException: Cannot invoke "java.util.List.isEmpty()" because the return value of "com.weiyu.model.CapitalInfoQueryDTO.getCreateDate()" is null。
这意味着在 Controller 层,您尝试调用 getCreateDate() 返回的列表的 isEmpty() 方法,但 getCreateDate() 返回了 null。
解决方案:
您需要在 Service 层的调用之前,在 Controller 层对 DTO 的 createDate 字段进行初始化,或者修改 DTO 类使其默认初始化。
方案1:在 Controller 中初始化(推荐)
在 Controller 的 queryList 方法中调用 Service 之前,先检查并初始化 createDate:
java
@PostMapping("/queryList")
public Result queryList(@RequestBody CapitalInfoQueryDTO queryDTO) {
// 初始化 createDate 字段,避免为 null
if (queryDTO.getCreateDate() == null) {
queryDTO.setCreateDate(new ArrayList<>());
}
// 调用 Service 方法
List<CapitalInfoVO> result = capitalInfoService.queryList(queryDTO);
return Result.success(result);
}
方案2:在 DTO 类中默认初始化(更彻底)
在 CapitalInfoQueryDTO 类中为 createDate 字段设置默认值:
java
public class CapitalInfoQueryDTO {
// 其他字段...
private List<String> createDate = new ArrayList<>();
// getter 和 setter 方法
public List<String> getCreateDate() {
return createDate;
}
public void setCreateDate(List<String> createDate) {
this.createDate = createDate;
}
}
方案3:在 Service 方法的开头进行防御性检查
虽然 Service 方法中已经有了 null 检查,但为了更安全,您可以在方法开头添加:
java
public List<CapitalInfoVO> queryList(@NotNull CapitalInfoQueryDTO queryDTO) {
// 防御性检查:确保 createDate 不为 null
if (queryDTO.getCreateDate() == null) {
queryDTO.setCreateDate(new ArrayList<>());
}
LambdaQueryWrapper<CapitalInfo> queryWrapper = new LambdaQueryWrapper<>();
// ... 其余代码
}
方案4:修复 Controller 中可能的 isEmpty() 调用
检查 CapitalInfoController.java 的第46行,看看是否有这样的代码:
java
// 错误示例:如果 queryDTO.getCreateDate() 为 null,会抛空指针异常
if (!queryDTO.getCreateDate().isEmpty()) {
// 做一些操作
}
// 正确示例:先检查是否为 null
if (queryDTO.getCreateDate() != null && !queryDTO.getCreateDate().isEmpty()) {
// 做一些操作
}
建议:
-
采用方案2(在 DTO 类中默认初始化)是最彻底的方法,可以确保无论何时调用
getCreateDate()都不会返回null。 -
如果您无法修改 DTO 类,那么采用方案1(在 Controller 中初始化)也是一个不错的选择。
-
同时,也需要检查您的 Controller 代码,确保不会直接调用
getCreateDate().isEmpty()而不进行空值检查。
这样处理后,您的 Service 方法中的条件判断 queryDTO.getCreateDate() != null && queryDTO.getCreateDate().size() == 2 就能正常工作了。
修改后的代码:
/**
* 获取资金信息列表
*/
public List<CapitalInfoVO> queryList(@NotNull CapitalInfoQueryDTO queryDTO) {
// 处理日期范围,避免为 null
if (queryDTO.getCreateDate() == null) {
queryDTO.setCreateDate(new ArrayList<>());
}
LocalDateTime beginDateTime = null;
LocalDateTime endDateTime = null;
if (queryDTO.getCreateDate() != null && queryDTO.getCreateDate().size() == 2) {
List<LocalDateTime> dateTimeRange = DateUtils.parseDateTimeRange(queryDTO.getCreateDate());
if (dateTimeRange.size() == 2) {
beginDateTime = dateTimeRange.get(0);
endDateTime = dateTimeRange.get(1);
}
}
LambdaQueryWrapper<CapitalInfo > queryWrapper = new LambdaQueryWrapper<>();
// 构造查询条件
queryWrapper
// 模糊查询 - 资金序号
.like(StringUtils.hasText(queryDTO.getCapitalNo()), CapitalInfo::getCapitalNo, queryDTO.getCapitalNo())
// 模糊查询 - 资金名称
.like(StringUtils.hasText(queryDTO.getCapitalName()), CapitalInfo::getCapitalName, queryDTO.getCapitalName())
// 精确查询 - 资金类别
.eq(StringUtils.hasText(queryDTO.getCapitalType()), CapitalInfo::getCapitalType, queryDTO.getCapitalType())
// 精确查询 - 指标类别
.eq(StringUtils.hasText(queryDTO.getCapitalIndexType()), CapitalInfo::getCapitalIndexType, queryDTO.getCapitalIndexType())
// 模糊查询 - 资金账户
.like(StringUtils.hasText(queryDTO.getCapitalAccount()), CapitalInfo::getCapitalAccount, queryDTO.getCapitalAccount())
// 精确查询 - 资金来源
.eq(StringUtils.hasText(queryDTO.getCapitalSource()), CapitalInfo::getCapitalSource, queryDTO.getCapitalSource())
// 精确查询 - 指标来源
.eq(StringUtils.hasText(queryDTO.getCapitalIndexSource()), CapitalInfo::getCapitalIndexSource, queryDTO.getCapitalIndexSource())
// 精确查询 - 资金年份
.eq(queryDTO.getCapitalYear() != null, CapitalInfo::getCapitalYear, queryDTO.getCapitalYear())
// 精确查询 - 资金状态
.eq(queryDTO.getCapitalState() != null, CapitalInfo::getCapitalState, queryDTO.getCapitalState())
// 模糊查询 - 备注信息
.like(StringUtils.hasText(queryDTO.getRemark()), CapitalInfo::getRemark, queryDTO.getRemark())
// between - 创建日期
.between(
queryDTO.getCreateDate().size() == 2,
CapitalInfo::getCreateTime,
beginDateTime,
endDateTime
)
// 倒序排序 - 资金年份
.orderByDesc(CapitalInfo::getCapitalYear)
// 倒序排序 - 主键id
.orderByDesc(CapitalInfo::getId);
List<CapitalInfo> capitalInfos = capitalInfoMapper.selectList(queryWrapper);
// List<CapitalInfo> -> List<CapitalInfoVO>
return capitalInfos.stream()
.map(capitalInfo -> {
CapitalInfoVO capitalInfoVO = new CapitalInfoVO();
BeanUtils.copyProperties(capitalInfo, capitalInfoVO);
return capitalInfoVO;
})
.collect(Collectors.toList());
}
更多推荐


所有评论(0)