以下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 表示您尝试访问一个空列表的第一个元素。

问题分析:

  1. 当 queryDTO.getCreateDate() 为 null 或空列表时,调用 .size() 会导致空指针异常,但这里显然不是这种情况,因为您已经检查了 .size() == 2

  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)
    // ... 排序条件

建议:

  1. 检查 DateUtils.parseDateTimeRange 方法:这个方法可能在某些输入下返回空列表。您需要确保它正确处理输入并返回预期的结果。

  2. 添加日志记录:记录解析失败的情况,以便调试。

  3. 防御性编程:在处理可能返回空值的方法时,始终进行空值检查。

这样修改后,您的代码将更加健壮,不会因为 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()) {
    // 做一些操作
}

建议:

  1. 采用方案2(在 DTO 类中默认初始化)是最彻底的方法,可以确保无论何时调用 getCreateDate() 都不会返回 null

  2. 如果您无法修改 DTO 类,那么采用方案1(在 Controller 中初始化)也是一个不错的选择。

  3. 同时,也需要检查您的 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());
    }

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐