在 Java Web 开发中,与数据库交互是不可避免的,而 JDBC(Java Database Connectivity) 是 Java 官方提供的标准数据库连接接口,几乎所有 Java 项目中都用过它。
本文通过一个完整示例,带你从零实现 增(Insert)、删(Delete)、改(Update)、查(Select) 四大功能,并配合流程图、表结构图深入分析 JDBC 的执行原理与优化方案。

一、JDBC 基本工作流程

       JDBC 是一套标准 API,任何数据库厂商只要提供 JDBC 驱动,就可以通过相同的代码访问不同数据库。它的基本执行步骤如下:

  1. 加载数据库驱动(Class.forName)

  2. 建立数据库连接(DriverManager.getConnection)

  3. 创建 Statement 对象(connection.createStatement)

  4. 执行 SQL 语句(executeQuery / executeUpdate)

  5. 处理结果集(ResultSet)

  6. 释放资源(关闭 ResultSet、Statement、Connection)

二、数据库表结构设计

我们以一个 qwe 表为例,存储学生信息。

表结构图:

+---------+-------------+----------+-------------+
| 字段名   | 数据类型    | 约束      | 描述        |
+---------+-------------+----------+-------------+
| id      | INT         | 主键自增  | 学生编号    |
| name    | VARCHAR(50) | NOT NULL | 学生姓名    |
| age     | INT         |          | 年龄        |
| sex     | VARCHAR(5)  |          | 性别        |
| classid | INT         |          | 班级ID      |
+---------+-------------+----------+-------------+

SQL 创建语句:

CREATE TABLE qwe (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50) NOT NULL,age INT,sex VARCHAR(5),classid INT
);

三、完整 JDBC 代码实现 CRUD

以下代码基于 MySQL 8.0 驱动,适用于 Java SE / Java Web 项目。

package com.qcby.db;import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;/*** JDBC 操作 MySQL 实现增删改查* 适用于 Java SE / Java Web*/
public class Test {public static void main(String[] args) {// SQL 示例(注意:实际项目中应使用 PreparedStatement)String sqlSelect = "SELECT * FROM qwe";String sqlInsert = "INSERT INTO qwe(name, age, sex, classid) VALUES('ppp', 18, '女', 3)";String sqlUpdate = "UPDATE qwe SET name = '修改后的名字' WHERE id = 1";String sqlDelete = "DELETE FROM qwe WHERE id = 2";// 调用方法System.out.println(search(sqlSelect));System.out.println("插入数据条数:" + add(sqlInsert));System.out.println("修改数据条数:" + update(sqlUpdate));System.out.println("删除数据条数:" + delete(sqlDelete));}/*** 查询方法* @param sql 查询语句* @return JSON 格式的查询结果*/public static String search(String sql) {try {// 1. 加载驱动Class.forName("com.mysql.cj.jdbc.Driver");// 2. 获取连接String url = "jdbc:mysql://localhost:3306/javaweb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai";String user = "root";String password = "123456";Connection connection = DriverManager.getConnection(url, user, password);// 3. 创建 Statement 对象Statement statement = connection.createStatement();// 4. 执行查询ResultSet resultSet = statement.executeQuery(sql);// 5. 封装结果为 JSON 格式StringBuilder res = new StringBuilder("[");while (resultSet.next()) {int id = resultSet.getInt("id");String name = resultSet.getString("name");String sex = resultSet.getString("sex");int age = resultSet.getInt("age");int classid = resultSet.getInt("classid");res.append(String.format("{\"id\":%d,\"name\":\"%s\",\"sex\":\"%s\",\"age\":%d,\"classid\":%d},",id, name, sex, age, classid));}if (res.length() > 1) {res.setLength(res.length() - 1); // 去掉最后的逗号}res.append("]");// 6. 释放资源(建议在 finally 块中关闭)resultSet.close();statement.close();connection.close();return res.toString();} catch (Exception e) {e.printStackTrace();return "";}}// 添加public static int add(String sql) {return executeUpdate(sql);}// 修改public static int update(String sql) {return executeUpdate(sql);}// 删除public static int delete(String sql) {return executeUpdate(sql);}/*** 公共执行方法(Insert、Update、Delete)*/private static int executeUpdate(String sql) {try {Class.forName("com.mysql.cj.jdbc.Driver");String url = "jdbc:mysql://localhost:3306/javaweb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai";String user = "root";String password = "123456";Connection connection = DriverManager.getConnection(url, user, password);Statement statement = connection.createStatement();int num = statement.executeUpdate(sql);statement.close();connection.close();return num;} catch (Exception e) {e.printStackTrace();return 0;}}
}

改进建议:

  • 资源关闭:推荐用 try-with-resources 自动关闭 Connection、Statement、ResultSet,避免忘记关闭导致连接泄露。

  • 防 SQL 注入:实际开发中应使用 PreparedStatement 而不是直接拼接字符串。

四、关键知识点详解

1. 驱动加载

Class.forName("com.mysql.cj.jdbc.Driver");
  • MySQL 8.x 驱动类com.mysql.cj.jdbc.Driver

  • 为什么手动加载? 早期 JDBC 版本需要显式加载驱动,现在有 SPI 自动加载机制,但手动加载能提高兼容性。

  • 常见报错ClassNotFoundException,说明 mysql-connector-java 依赖未导入。

2. 数据库连接 URL

jdbc:mysql://localhost:3306/javaweb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
  • useUnicode=true:支持 Unicode 字符

  • characterEncoding=UTF-8:使用 UTF-8 编码

  • serverTimezone=Asia/Shanghai:解决时区问题

3. Statement 与 PreparedStatement区别

特性StatementPreparedStatement
SQL 注入有风险防注入
执行效率每次执行都编译 SQL预编译,提高性能
参数绑定手动拼接setString/setInt
推荐程度高(实际项目都用这个)
  • Statement:直接拼接 SQL(有 SQL 注入风险)

  • PreparedStatement:预编译 SQL,防止注入,并提高执行效率(推荐)

五、在 Servlet 中调用

在 Java Web 中,可以将这个 JDBC 工具类放到 com.utils 包中,然后在 Servlet 中调用,例如:

@WebServlet("/search")
public class SearchServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {// 查询所有数据String sql = "SELECT * FROM qwe";String resultJson = Test.search(sql);// 设置响应类型为 JSONresponse.setContentType("application/json;charset=UTF-8");// 返回数据给前端response.getWriter().write(resultJson);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {// 如果需要支持 POST,可以在这里处理doGet(request, response);}
}

优化建议:

  1. 统一编码:在过滤器中设置 request.setCharacterEncoding("UTF-8")

  2. 返回 JSON 工具类:用 GsonJackson 代替手写 JSON。

  3. 异常处理:Servlet 里不要直接 printStackTrace(),建议记录到日志文件。

七、总结

       本文通过完整代码演示了如何用 JDBC 操作 MySQL 实现增删改查,并配合流程图、表结构图解释了其执行过程。
在实际项目中,我们应结合 连接池 + PreparedStatement + DAO 封装,从而让代码更安全、更高效、更易维护。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/918427.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/918427.shtml
英文地址,请注明出处:http://en.pswp.cn/news/918427.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTTP 请求返回状态码和具体含义?200、400、403、404、502、503、504等

HTTP 状态码是服务器对客户端请求的响应状态标识,分为五大类(以第一位数字区分),常用状态码如下: 1. 信息类(1xx):请求已接收,继续处理 100 Continue:服务器已…

13-netty基础-手写rpc-消费方生成代理-05

netty系列文章: 01-netty基础-socket02-netty基础-java四种IO模型03-netty基础-多路复用select、poll、epoll04-netty基础-Reactor三种模型05-netty基础-ByteBuf数据结构06-netty基础-编码解码07-netty基础-自定义编解码器08-netty基础-自定义序列化和反序列化09-n…

ThreadLocal有哪些内存泄露问题,如何避免?

每个Thread都有一个ThreadLocal.ThreadLocalMap的map,该map的key为ThreadLocal实例,它为一个弱引 用,我们知道弱引用有利于GC回收。当ThreadLocal的key null时,GC就会回收这部分空间,但是value却不一 定能够被回收&am…

从0到1学LangChain之Agent代理:解锁大模型应用新姿势

从0到1学LangChain之Agent代理&#xff1a;解锁大模型应用新姿势 本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型开发 学习视频/籽料/面试题 都在这>>Github<< 什么是 LangChain Agent 代理 如果把大模型比作一个超级大脑&#xff0c;那么…

Spring Boot 2.6.0+ 循环依赖问题及解决方案

Spring Boot 2.6.0 循环依赖问题及解决方案 目录 背景解决方案 1. 配置文件开启循环依赖&#xff08;侵入性最低&#xff0c;临时方案&#xff09;2. Lazy 延迟注入&#xff08;侵入性低&#xff0c;推荐优先尝试&#xff09;3. 手动从容器获取&#xff08;ApplicationContex…

本地代码上传Github步骤

1.注册Github账号 2.下载git客户端 下载、安装步骤可以参考网站&#xff1a;(6 封私信 / 10 条消息) 手把手教你用git上传项目到GitHub&#xff08;图文并茂&#xff0c;这一篇就够了&#xff09;&#xff0c;相信你一定能成功&#xff01;&#xff01; - 知乎 3.在Github上…

5G NR 非地面网络 (NTN) 5G、太空和统一网络

非地面网络 5G 和太空&#xff1a;对 NTN 测试与测量的影响NTN 基站测试与测量NTN 用户设备的测试设备R&SSMW200A 矢量信号发生器R&SSMBV100B 矢量信号发生器总结5G 和太空&#xff1a;对 NTN 测试与测量的影响 5G 非地面网络 (NTN) 是无线通信向全球性星基和机载通信…

少儿编程比赛(如蓝桥杯、创意编程大赛等)的题目类型、知识点及难度总结

以下是针对主流少儿编程比赛&#xff08;如蓝桥杯、创意编程大赛等&#xff09;的题目类型、知识点及难度总结&#xff0c;结合了Scratch和C等语言的真题分析&#xff0c;帮助备赛或教学参考&#xff1a; 一、基础操作与交互题&#xff08;适合6~10岁&#xff09; 考察图形化编…

SIFThinker: Spatially-Aware Image Focus for Visual Reasoning

SIFThinker: Spatially-Aware Image Focus for Visual Reasoning Authors: Zhangquan Chen, Ruihui Zhao, Chuwei Luo, Mingze Sun, Xinlei Yu, Yangyang Kang, Ruqi Huang 相关工作总结 视觉思维链推理 最近的研究表明&#xff0c;通过上下文学习逐步推理可以显著提升大型…

学习嵌入式第二十五天

IO 1.概念 IO指input/outputLinux中一切皆文件IO的操作对象是文件 2.文件一段数据的集合文件通常存放在外存中&#xff0c;掉电后数据不丢失分类b(block&#xff0c;块设备文件) 按块扫描信息的文件。通常存储类型的设备为块设备文件。文件IOc(character&#xff0c;字符设备文…

本地部署接入 whisper + ollama qwen3:14b 总结字幕

1. 实现功能 M4-1 接入 whisper ollama qwen3:14b 总结字幕 自动下载视频元数据如果有字幕&#xff0c;只下载字幕使用 ollama 的 qwen3:14b 对字幕内容进行总结 2.运行效果 &#x1f50d; 正在提取视频元数据… &#x1f4dd; 正在下载所有可用字幕… [youtube] Extracting U…

【13-向量化-高效计算】

研究者能够扩展神经网络并构建非常大型网络的原因之一&#xff0c;就是神经网络可以被向量化&#xff0c;vectorized&#xff1b;可以非常高效地用矩阵地乘法实现。 事实上&#xff0c;并行计算硬件&#xff0c;例如GPU&#xff0c;一些CPU的功能&#xff0c;非常擅长进行非常大…

论文中PDF的公式如何提取-公式提取

Mathcheap - An AI-powered, free alternative to Mathpix Snip. 从PDF中截图公式&#xff0c;之后 ctrl V 转换成功 &#xff0c;提取成功 复制到word中&#xff0c;是这样的 这显然不是我们需要的。 可以使用Axmath 复制进去Axmath 就能正常显示公式。 之后再插入word…

用 Flink SQL 和 Paimon 打造实时数仓:深度解析与实践指南

1. 实时数仓的魅力&#xff1a;从离线到分钟级的飞跃实时数仓&#xff0c;听起来是不是有点高大上&#xff1f;其实它没那么神秘&#xff0c;但确实能让你的数据处理能力像坐上火箭一样飙升&#xff01;传统的离线数仓&#xff0c;像 Hadoop 生态的 Hive&#xff0c;动辄小时级…

【已解决】报错:WARNING: pip is configured with locations that require TLS/SSL

一、问题背景二、问题分析1. SSL模块缺失的本质2. Anaconda环境特点三、问题表现四、解决方案详解1. 完整配置环境变量2. 添加环境变量的步骤3. 测试验证五、实战示例六、附加建议七、总结八、参考链接一、问题背景 在Windows 10系统中使用Python的包管理工具pip时&#xff0c…

Java项目基本流程(三)

一、页面初始化阶段&#xff08;加载即执行&#xff09;加载栏目列表&#xff08;同步请求&#xff09;发送同步 AJAX 请求到SearchChannel接口&#xff0c;获取所有栏目数据。清空下拉框&#xff08;.channelid&#xff09;后&#xff0c;先添加 “全部” 选项&#xff0c;再循…

鹧鸪云光伏仿真:项目前期决策的“数据明灯”

曾有一处光伏项目&#xff0c;在精心筹备数月后终于建成&#xff0c;却在运行初期即因未充分评估山体遮挡影响&#xff0c;导致实际发电量较预期大幅降低近一成。前期决策中的微小疏漏&#xff0c;往往成为项目经济性与可行性的致命伤。而鹧鸪云光伏仿真软件正是一盏照亮前路的…

开发指南129-基础类-BaseController

所有接口都需要继承BaseControllerBaseController里有很多有用的方法&#xff0c;现举例最重要的几个&#xff1a;1、getURI返回接口地址&#xff0c;就是PostMapping或GetMapping中定义的接口地址。常用于返回值中&#xff0c;例如接口的异常处理&#xff1a;try {// 处理逻辑…

C++高频知识点(十八)

文章目录86. C多线程中&#xff0c;锁的实现方式有哪些&#xff1f;1. 互斥锁&#xff08;Mutex&#xff09;2. 递归互斥锁&#xff08;Recursive Mutex&#xff09;3. 读写锁&#xff08;Shared Mutex&#xff09;4. 自旋锁&#xff08;Spinlock&#xff09;5. 条件变量&#…

【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day1

&#x1f525;个人主页&#xff1a;草莓熊Lotso &#x1f3ac;作者简介&#xff1a;C研发方向学习者 &#x1f4d6;个人专栏&#xff1a; 《C语言》 《数据结构与算法》《C语言刷题集》《Leetcode刷题指南》 ⭐️人生格言&#xff1a;生活是默默的坚持&#xff0c;毅力是永久的…