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() 设置,解决脏读、不可重复读、幻读问题。

相关推荐
IMPYLH1 小时前
Lua 的 tostring 函数
开发语言·笔记·junit·单元测试·lua
天天摸鱼的java工程师1 小时前
🐇RabbitMQ 从入门到业务实战:一个 Java 程序员的实战手记
java·后端
uup1 小时前
多线程下线程安全的单例模式实现缺陷
java
橙序员小站1 小时前
Java 接入Pinecone搭建知识库踩坑实记
java·开发语言·人工智能
豆沙沙包?1 小时前
2025年--Lc313-662. 二叉树最大宽度--java版
java·开发语言
CoderYanger1 小时前
C.滑动窗口——2762. 不间断子数组
java·开发语言·数据结构·算法·leetcode·1024程序员节
BBB努力学习程序设计1 小时前
Java接口:定义行为的"契约"
java
2401_837088501 小时前
Integer.MIN_VALUE 是什么意思?
java·开发语言·算法