当前位置: 首页 > news >正文

SQL 执行异常排查 java.sql.SQLException:从 SQLException 说起

网罗开发(小红书、快手、视频号同名)

  大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。

图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG

我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。

展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索“展菲”,即可纵览我在各大平台的知识足迹。
📣 公众号“Swift社区”,每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
💬 微信端添加好友“fzhanfei”,与我直接交流,不管是项目瓶颈的求助,还是行业趋势的探讨,随时畅所欲言。
📅 最新动态:2025 年 3 月 17 日
快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!


文章目录

    • 前言
    • 场景描述:常见的 SQLException 问题
    • 排查思路:怎么快速锁定问题?
    • Demo:带日志的 SQL 执行封装
    • 结合实际开发的应用
    • 总结

前言

在日常开发中,大家应该或多或少都遇到过这种情况:SQL 在本地跑得好好的,一放到服务里执行就报 java.sql.SQLException。很多同学看到这个异常时,第一反应就是“是不是数据库挂了?”。其实绝大多数情况跟数据库无关,而是 SQL 拼接、参数绑定或者日志缺失导致的。

这篇文章我结合一个小 Demo,带大家看一下 SQLException 的常见原因,以及如何一步步排查。

场景描述:常见的 SQLException 问题

假设我们有一张 users 表,结构很简单:

CREATE TABLE users (id BIGINT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(50) NOT NULL,age INT
);

在 Java 项目里写了一个最普通的查询:

String sql = "SELECT * FROM users WHERE username = ? AND age = ?";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, "zhangfei");
ps.setInt(2, 18);ResultSet rs = ps.executeQuery();

看似没问题,但在真实项目里,很容易因为下面几个问题报 SQLException

  1. SQL 拼接错误:比如忘了 AND,或者参数占位符数量不对。
  2. 参数绑定异常:明明是数字,结果 setString();或者顺序错了。
  3. SQL 没有打印日志:导致无法复现真实执行的 SQL。

排查思路:怎么快速锁定问题?

遇到 SQLException 时,不要慌,通常从以下几个角度来排查:

  1. 打印完整 SQL
    很多时候,你以为你执行的是 SELECT * FROM users WHERE username = 'zhangfei',实际上可能变成了 SELECT * FROM users WHERE username = 'null'

  2. 检查参数绑定
    确认每个 ? 是否都被正确赋值,并且类型匹配。

  3. 用日志记录 SQL
    不仅要打印原始 SQL,还要把 参数替换后的 SQL 打出来,方便直接拿去数据库执行。

Demo:带日志的 SQL 执行封装

我们可以写一个简单的工具方法来封装 SQL 执行和日志打印。这样每次执行 SQL 时,都能清晰看到完整的 SQL。

import java.sql.*;
import java.util.Arrays;public class JdbcHelper {public static void executeQuery(Connection conn, String sql, Object... params) {try (PreparedStatement ps = conn.prepareStatement(sql)) {// 参数绑定for (int i = 0; i < params.length; i++) {ps.setObject(i + 1, params[i]);}// 打印完整 SQLSystem.out.println("Executing SQL: " + buildFullSql(sql, params));try (ResultSet rs = ps.executeQuery()) {while (rs.next()) {System.out.println("User: " + rs.getString("username") + ", Age: " + rs.getInt("age"));}}} catch (SQLException e) {System.err.println("SQL 执行异常: " + e.getMessage());e.printStackTrace();}}// 将参数替换到 SQL 中(简易版)private static String buildFullSql(String sql, Object... params) {String fullSql = sql;for (Object param : params) {String value = (param instanceof String) ? "'" + param + "'" : String.valueOf(param);fullSql = fullSql.replaceFirst("\\?", value);}return fullSql;}// Demo 入口public static void main(String[] args) throws Exception {Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb", "root", "password");executeQuery(conn, "SELECT * FROM users WHERE username = ? AND age = ?", "zhangfei", 18);}
}

运行效果:

Executing SQL: SELECT * FROM users WHERE username = 'zhangfei' AND age = 18
User: zhangfei, Age: 18

一旦 SQL 写错,比如参数缺失,就能立刻在日志里看到:

Executing SQL: SELECT * FROM users WHERE username = 'zhangfei' AND age = null
SQL 执行异常: Unknown column 'null' in 'where clause'

是不是就一目了然了?

结合实际开发的应用

在真实的业务开发中,SQLException 的定位通常会踩到几个坑:

  • 多服务场景:调用链太长,不知道 SQL 是在哪个微服务里执行的。
  • ORM 框架二次封装:比如 MyBatis,把 SQL 隐藏在 XML 里,导致排查困难。
  • 日志打印不全:只打印了原始 SQL,没有参数,运维无法复现。

因此,建议大家在项目里加一个 SQL 拦截器,不论是 MyBatis 的 Interceptor,还是 JPA 的日志配置,都要确保能拿到 完整 SQL

总结

java.sql.SQLException 本质上不是“数据库坏了”,而是代码逻辑和 SQL 执行之间的沟通问题。核心思路就是:

  1. 先把完整 SQL 打印出来
  2. 确认参数绑定是否正确
  3. 保证日志可复现

这样基本上 90% 的 SQL 问题都能快速解决。

http://www.dtcms.com/a/422497.html

相关文章:

  • uniapp 运行/发版微信小程序
  • vue2动态实现多Y轴echarts图表,及节点点击事件
  • MySQL 数据导出及备份方法
  • 公司网站建设设计如何收费网站诊断分析
  • 网站设计技巧如何看网站是用什么程序做的
  • Pythoner 的Flask项目实践-Mapboxgl-v3全球3D地图体验之地标性 3D 建筑物(迪拜哈里发大厦三维模型展示)
  • 学习机器学习要学习和掌握哪些知识?
  • 化学专业大型语言模型——SparkChemistry-X1-13B本地部署教程:洞察分子特性,精准预测化学行为
  • qt5下载
  • c 网站开发代码wordpress调用副标题
  • vscode 不能跳转 ERR_OSSL_EVP_BAD_DECRYPT
  • 大数据毕业设计选题推荐-基于大数据的全球产品库存数据分析与可视化系统-大数据-Spark-Hadoop-Bigdata
  • GitPuk入门到实战(4) - 如何进行分支管理
  • 基于AC6351D2做无线键盘
  • 【STM32项目开源】基于STM32的智能路灯控制系统
  • 超越编辑器:IntelliJ IDEA,如何成为Java开发的智慧引擎
  • Day31_【 NLP _1.文本预处理 _(2)文本张量表示方法】
  • UNIX下C语言编程与实践3-Vi 编辑器从入门到精通:快捷键使用与高效编辑技巧
  • 网站 设计 案例 简单易订货小程序怎么收费
  • 锂离子扩散能垒计算如何驱动高性能电池研发-测试GO
  • rtsoft 的“整理”流程
  • C++程序设计上机作业(1)
  • 【C++STL :vector类 (一) 】详解vector类的使用层vector实践:算法题
  • 机器学习项目结构目录的构建
  • 2022 年 CSP-J(中国计算机学会软件能力认证入门级)初赛真题与答案解析
  • 常州市建设工程网站衡水做网站
  • 北京58网站建设wordpress在线商城插件
  • 2025年计算机网络与信号处理国际会议(CNSP 2025)
  • 利用css的动画效果制作轮播图
  • docker镜像和