JDBC 笔记

目录

[一、JDBC 核心概念](#一、JDBC 核心概念)

[1. 本质](#1. 本质)

[2. 核心组件(必须掌握)](#2. 核心组件(必须掌握))

[二、实操步骤(以 MySQL 8.0+ 为例)](#二、实操步骤(以 MySQL 8.0+ 为例))

[1. 环境准备](#1. 环境准备)

[2. 基础 CRUD 代码模板](#2. 基础 CRUD 代码模板)

(1)查询操作(SELECT)

[(2)新增 / 修改 / 删除(INSERT/UPDATE/DELETE)](#(2)新增 / 修改 / 删除(INSERT/UPDATE/DELETE))

三、关键技巧与避坑点

[1. 防 SQL 注入](#1. 防 SQL 注入)

[2. 事务管理](#2. 事务管理)

[3. 资源释放](#3. 资源释放)

[4. 连接池优化(生产必备)](#4. 连接池优化(生产必备))

四、常见问题排查

[1. 驱动加载异常(ClassNotFoundException)](#1. 驱动加载异常(ClassNotFoundException))

[2. 时区错误(serverTimezone)](#2. 时区错误(serverTimezone))

[3. 连接被拒绝(Connection refused)](#3. 连接被拒绝(Connection refused))

五、进阶拓展


一、JDBC 核心概念

1. 本质

Java 操作关系型数据库的标准 API(接口集合),由数据库厂商提供驱动实现(如 MySQL 的 mysql-connector-java),屏蔽不同数据库底层差异,实现「一次编码,多库兼容」。

2. 核心组件(必须掌握)

组件 作用 关键细节
DriverManager 驱动管理 + 获取连接 加载驱动(MySQL 8.0+ 可省略)、getConnection() 获连接
Connection 数据库连接会话 事务控制(提交 / 回滚)、创建执行对象
PreparedStatement 预编译 SQL 执行对象(推荐) 防 SQL 注入、占位符 ? 赋值、性能更优
Statement 静态 SQL 执行对象 无预编译,有注入风险,仅用于简单静态 SQL
ResultSet 查询结果集 游标遍历(next())、按列名 / 索引取值

二、实操步骤(以 MySQL 8.0+ 为例)

1. 环境准备

  • 导入驱动依赖(Maven 示例):

xml

复制代码
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
    <scope>runtime</scope>
</dependency>
  • 连接参数配置:

    • URL:jdbc:mysql://localhost:3306/数据库名?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true

    • 用户名:root(默认)

    • 密码:数据库登录密码

2. 基础 CRUD 代码模板

(1)查询操作(SELECT)

java

复制代码
import java.sql.*;
​
public class JdbcSelectDemo {
    public static void main(String[] args) {
        // 1. 声明资源(try-with-resources 可自动关闭)
        try (Connection conn = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC",
                "root", "123456");
             PreparedStatement pstmt = conn.prepareStatement("SELECT id, name FROM user WHERE age > ?");
             ResultSet rs = pstmt.executeQuery()) {
​
            // 2. 占位符赋值(索引从 1 开始)
            pstmt.setInt(1, 18);
​
            // 3. 遍历结果集
            while (rs.next()) {
                int id = rs.getInt("id"); // 按列名取值(推荐)
                String name = rs.getString(2); // 按列索引取值(不推荐,易出错)
                System.out.println("id: " + id + ", name: " + name);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
(2)新增 / 修改 / 删除(INSERT/UPDATE/DELETE)

java

复制代码
public class JdbcModifyDemo {
    public static void main(String[] args) {
        String sql = "INSERT INTO user(name, age) VALUES (?, ?)";
        try (Connection conn = DriverManager.getConnection(URL, USER, PWD);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
​
            pstmt.setString(1, "张三");
            pstmt.setInt(2, 22);
​
            int affectedRows = pstmt.executeUpdate(); // 返回受影响行数
            System.out.println("新增成功,影响行数:" + affectedRows);
​
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

三、关键技巧与避坑点

1. 防 SQL 注入

  • 错误示例(Statement 拼接 SQL):

java

复制代码
String name = "admin' OR 1=1 --";
String sql = "SELECT * FROM user WHERE name='" + name + "'"; 
// 拼接后 SQL:SELECT * FROM user WHERE name='admin' OR 1=1 --'(查询所有数据)
  • 正确做法:使用 PreparedStatement 占位符,自动转义特殊字符。

2. 事务管理

JDBC 默认自动提交事务,手动控制事务步骤:

java

复制代码
try (Connection conn = DriverManager.getConnection(URL, USER, PWD)) {
    conn.setAutoCommit(false); // 关闭自动提交
    // 执行多个 SQL 操作
    pstmt1.executeUpdate();
    pstmt2.executeUpdate();
    conn.commit(); // 全部成功则提交
} catch (SQLException e) {
    conn.rollback(); // 异常则回滚
    e.printStackTrace();
}

3. 资源释放

  • 推荐使用 try-with-resources 语法(自动关闭实现 AutoCloseable 接口的资源),无需手动写 finally 关闭。

  • 手动关闭顺序:ResultSet → PreparedStatement → Connection(逆序创建顺序)。

4. 连接池优化(生产必备)

  • 问题:频繁创建 / 销毁 Connection 耗时耗资源。

  • 解决方案:使用连接池(HikariCP 性能最优,Spring Boot 默认),示例:

java

复制代码
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
​
public class HikariDemo {
    public static void main(String[] args) throws SQLException {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(URL);
        config.setUsername(USER);
        config.setPassword(PWD);
        config.setMaximumPoolSize(10); // 最大连接数
​
        HikariDataSource dataSource = new HikariDataSource(config);
        Connection conn = dataSource.getConnection(); // 从池获取连接
        // 使用后自动归还(conn.close() 不是真正关闭)
    }
}

四、常见问题排查

1. 驱动加载异常(ClassNotFoundException)

  • 原因:驱动类名错误、Maven 依赖未导入。

  • 解决:MySQL 8.0+ 驱动类是 com.mysql.cj.jdbc.Driver(5.x 是 com.mysql.jdbc.Driver),确认依赖已引入。

2. 时区错误(serverTimezone)

  • 解决方案:URL 中添加 serverTimezone=UTCserverTimezone=Asia/Shanghai

3. 连接被拒绝(Connection refused)

  • 检查:数据库服务是否启动、端口 3306 是否开放、URL 中主机 / 端口是否正确。

五、进阶拓展

  1. 通用工具类:封装连接获取、SQL 执行方法,减少重复代码。

  2. 批处理 :使用 addBatch() + executeBatch() 批量插入 / 更新,提升效率。

  3. 结果集映射 :手动映射 ResultSet 到 Java 实体类(或使用 MyBatis 等框架自动映射)。

  4. 事务隔离级别 :通过 conn.setTransactionIsolation() 设置,解决脏读、不可重复读、幻读问题。

相关推荐
曹牧35 分钟前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
wdfk_prog1 小时前
[Linux]学习笔记系列 -- [drivers][input]input
linux·笔记·学习
ouliten1 小时前
cuda编程笔记(36)-- 应用Tensor Core加速矩阵乘法
笔记·cuda
爬山算法1 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
kfyty7252 小时前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai
猫头虎2 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
李少兄2 小时前
在 IntelliJ IDEA 中修改 Git 远程仓库地址
java·git·intellij-idea
忆~遂愿2 小时前
ops-cv 算子库深度解析:面向视觉任务的硬件优化与数据布局(NCHW/NHWC)策略
java·大数据·linux·人工智能
小韩学长yyds2 小时前
Java序列化避坑指南:明确这4种场景,再也不盲目实现Serializable
java·序列化
仟濹2 小时前
【Java基础】多态 | 打卡day2
java·开发语言