CONCAT函数使用中出现空指针异常问题分析

文章目录

前言

在项目中,遇到一个场景,使用mysql的CONCAT函数实现字段值拼接,出现如下报错:

总的来说:空指针异常。

  • 原始sql:
sql 复制代码
<select id="findFailedTaskNames" resultType="java.lang.String">
      SELECT
          CONCAT(software_name, '_', software_version, '_', developer) as taskName
      FROM
          xxx
      WHERE
          id IN
      <foreach collection="list" item="item" open="(" close=")" separator=",">
          #{item}
      </foreach>
</select>
  • 报错:

    2025-11-03 11:10:16.596 [jyh-detect-whl] traceId[] [http-nio-10002-exec-3] ERROR c.q.w.t.c.s.h.ControllerExceptionAdvice - [handleRuntimeException,83] - 请求地址'/detect/task/storage/delete/tasks',发生未知异常.
    java.lang.NullPointerException: null
    at cn.qbs.wa.teach.course.standard.service.impl.CodeCheckTaskServiceImpl.lambdadeleteFailedTasks5(CodeCheckTaskServiceImpl.java:417)
    at java.base/java.util.stream.ReferencePipeline31.accept(ReferencePipeline.java:195)
    at java.base/java.util.ArrayListArrayListSpliterator.forEachRemaining(ArrayList.java:1655) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) at java.base/java.util.stream.ReduceOpsReduceOp.evaluateSequential(ReduceOps.java:913)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
    at cn.qbs.wa.teach.course.standard.service.impl.CodeCheckTaskServiceImpl.deleteFailedTasks(CodeCheckTaskServiceImpl.java:418)
    at cn.qbs.wa.teach.course.standard.service.impl.CodeCheckTaskServiceImplFastClassBySpringCGLIB372942fe.invoke()
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy.invokeMethod(CglibAopProxy.java:386)
    at org.springframework.aop.framework.CglibAopProxy.access000(CglibAopProxy.java:85) at org.springframework.aop.framework.CglibAopProxyDynamicAdvisedInterceptor.intercept(CglibAopProxy.java:704)
    at cn.qbs.wa.teach.course.standard.service.impl.CodeCheckTaskServiceImplEnhancerBySpringCGLIBe6d08e42.deleteFailedTasks()
    at cn.qbs.wa.teach.course.standard.controller.web.TrustApplyController.deleteFailedTasks(TrustApplyController.java:152)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

为什么?

这是因为,部分字段的值为null,在大多数数据库中(MySQL、PostgreSQL等),CONCAT 函数中任何参数为 NULL 都会导致整个结果为 NULL。

如何解决?

  • 使用 CONCAT_WS,CONCAT_WS 会忽略 NULL 值,只连接非 NULL 的部分。
  • 使用数据库特定的函数:
    • MySQL: IFNULL(字段名, '') 或 COALESCE(字段名, '')
    • PostgreSQL: COALESCE(字段名, '')
  • 使用 CASE WHEN
    • CASE WHEN 字段名 IS NULL THEN '' ELSE 字段名 END

总结

以上为个人学习分享,如有问题,欢迎指出:)

相关推荐
2603_965148117 小时前
如何解析JSON数据?API返回的商品信息处理教程
开发语言·数据库·python·自动化·json·api
ltl7 小时前
RocksDB 经典故障排查:L0、compaction 与 write stall
数据库
xfhuangfu9 小时前
Oracle中建立到CDB和PDB的连接
数据库·oracle·rpc
小小龙学IT9 小时前
DuckDB 深度实战:用 C++ 在进程内跑一个「分析型数据库」
数据库·c++
NineData9 小时前
DTCC 2026 预告|NineData CEO& 创始人叶正盛:面向 AI Agent 的数据库 DevOps 与数据复制实践
数据库·人工智能·数据库开发·devops·ninedata·数据库技术·dtcc
J_bean10 小时前
MySQL 事务是否必须手动开启?
数据库·mysql·数据库事务·自动提交·手动提交
J_bean10 小时前
MySQL InnoDB 如何检测死锁、判定死锁、处理死锁
数据库·mysql·死锁·死锁检测·处理死锁·死锁判定
浪子明X10 小时前
从 MongoDB 文档到关系模型:构建可重跑、可对账的数据迁移流水线
数据库·mongodb·oracle
杜子不疼.10 小时前
国产数据库撑起固井软件自主化:金仓 × 中海油服「海恒 Cemsol」落地解析
数据库
隔窗听雨眠10 小时前
GBase 8s并发控制深度解析:封锁机制、隔离级别与死锁处理全攻略
服务器·数据库·oracle