JDBC 完整笔记 + 核心 API 详解(入门到实战)

JDBC 完整笔记 + 核心 API 详解(入门到实战)

JDBC 完整笔记 + 核心 API 详解(入门到实战)

一、JDBC 概述

  1. 什么是 JDBC

JDBC(Java DataBase Connectivity):Java 数据库连接,是 Java 官方定义的一套操作所有关系型数据库的接口(API)。

  • 作用:Java 程序统一规范访问 MySQL、Oracle、SQLServer 等数据库,一套代码适配多数据库。

  • 本质:java.sql+javax.sql包下的接口、类、异常。

  1. JDBC 架构

  1. Java 应用程序:调用 JDBC 接口

  2. JDBC 接口(标准):Sun 定义规范

  3. 数据库驱动(实现类):数据库厂商实现 JDBC 接口(如mysql-connector-java

  4. 数据库服务:MySQL/Oracle 等

核心:面向接口编程,只操作 JDBC 接口,不直接接触驱动实现类。

  1. 使用前提

  1. 导入对应数据库驱动 jar 包

    1. MySQL 5.x:mysql-connector-java-5.1.xx.jar

    2. MySQL 8.x:mysql-connector-java-8.0.xx.jar(驱动类、URL 有变化)

  2. 项目中添加依赖(普通项目 / Maven)

Maven 依赖(MySQL8)

xml

<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency>

二、JDBC 核心六大核心 API(重点)

表格

接口 / 类作用
Driverjava.sql驱动接口,数据库厂商实现
DriverManagerjava.sql驱动管理类,获取数据库连接
Connectionjava.sql数据库连接对象,代表 Java 和数据库的通道
Statementjava.sqlSQL 语句执行对象(静态 SQL,有 SQL 注入风险)
PreparedStatementjava.sql预编译 SQL 对象(推荐,防注入、效率高)
ResultSetjava.sql结果集对象,封装数据库查询返回的数据

三、JDBC 标准执行 7 步(固定流程)

  1. 加载驱动

  2. 获取数据库连接 Connection

  3. 编写 SQL 语句

  4. 获取 SQL 执行对象(Statement/PreparedStatement)

  5. 执行 SQL,接收结果

  6. 处理结果(查询才需要)

  7. 释放资源(ResultSet → Statement → Connection)


四、逐个 API 详解 + 代码示例

  1. Driver 驱动接口 & 驱动加载

1.1 驱动类全限定名
  • MySQL 5.x:com.mysql.jdbc.Driver

  • MySQL 8.x:com.mysql.cj.jdbc.Driver(新增cj包,必须写对)

1.2 加载驱动方式

本质:通过反射加载驱动类,自动执行静态代码块完成驱动注册

// 方式1:Class.forName(全类名) 【主流写法】 Class.forName("com.mysql.cj.jdbc.Driver"); // 方式2:new 驱动对象(不推荐,硬编码) new com.mysql.cj.jdbc.Driver();

补充:MySQL 6.0+ 可省略加载驱动 驱动包内置META-INF/services/java.sql.Driver文件,自动加载驱动,但企业开发仍建议手动写,兼容性更好。


  1. DriverManager 驱动管理类(获取连接)

2.1 核心静态方法
// 获取数据库连接,返回 Connection 对象 public static Connection getConnection(String url, String user, String password)
2.2 URL 地址格式(关键)

通用格式:jdbc:数据库类型://数据库IP:端口/数据库名?参数

  • MySQL 标准 URL

  • plaintext

jdbc:mysql://localhost:3306/数据库名
  • 本机简写(localhost:3306 可省略)

  • plaintext

jdbc:mysql:///数据库名

MySQL8 必须追加时区参数(否则报错时区异常):

plaintext

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

参数说明:

  • useSSL=false:关闭 SSL 安全连接(本地测试必加)

  • serverTimezone=UTC:指定时区,解决时区报错

  • allowPublicKeyRetrieval=true:解决密码认证异常

2.3 代码获取连接
// 数据库信息 String url = "jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC"; String user = "root"; String pwd = "123456"; // 获取连接 Connection conn = DriverManager.getConnection(url, user, pwd); System.out.println(conn); // 不为null即连接成功

  1. Connection 连接对象(接口)

Connection是 Java 与数据库的会话通道,生命周期:一次连接。

3.1 核心方法
  1. 创建 SQL 执行对象

  2. java

  3. 运行

// 创建普通 Statement Statement createStatement() // 创建预编译 PreparedStatement(推荐) PreparedStatement prepareStatement(String sql)
  1. 事务管理(JDBC 事务核心)

  2. java

  3. 运行

// 关闭自动提交(开启事务),默认 true 自动提交 void setAutoCommit(boolean autoCommit) // 提交事务 void commit() // 回滚事务 void rollback() // 设置事务保存点(进阶) Savepoint setSavepoint()
  1. 关闭连接

void close()
3.2 事务使用示例
// 关闭自动提交(开启事务),默认 true 自动提交 void setAutoCommit(boolean autoCommit) // 提交事务 void commit() // 回滚事务 void rollback() // 设置事务保存点(进阶) Savepoint setSavepoint()

  1. Statement 静态执行对象(了解,不推荐)

4.1 作用

执行静态、固定拼接的 SQL 语句,存在 SQL 注入漏洞。

4.2 核心方法
// 执行 DQL 查询(select),返回结果集 ResultSet ResultSet executeQuery(String sql) // 执行 DML(insert/update/delete)、DDL,返回受影响行数 int executeUpdate(String sql) // 万能方法:可执行任意SQL,返回boolean(是否有结果集) boolean execute(String sql)
4.3 示例(SQL 注入风险演示)
// 拼接SQL,极易被注入 String name = "张三' or '1'='1"; String sql = "select * from user where name = '"+name+"'"; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); // 会查询出所有数据,注入成功

结论:正式开发禁止使用 Statement,一律用PreparedStatement


  1. PreparedStatement 预编译执行对象(⭐ 重点推荐)

5.1 特点
  1. 预编译 SQL:SQL 模板先发送数据库编译,后续只传参数,执行效率高

  2. 使用?占位符,参数单独设置,彻底防止 SQL 注入

  3. 支持批量操作

5.2 使用步骤
  1. 编写 SQL,使用?作为参数占位符(无单引号)

  2. 通过Connection创建对象,传入 SQL

  3. 调用setXxx(占位符索引, 值)?赋值(索引从 1 开始)

  4. 执行 SQL(无需再传 SQL 语句)

5.3 核心方法
(1)给占位符赋值 setXxx () 系列

根据字段类型选择对应方法:

// 通用格式:set类型(第几个?, 值) void setInt(int parameterIndex, int x) void setString(int parameterIndex, String x) void setDouble(int parameterIndex, double x) void setDate(int parameterIndex, Date x) void setObject(int parameterIndex, Object x) // 万能方法
(2)执行 SQL 方法(无参)
// 查询 select → 返回 ResultSet ResultSet executeQuery() // 增删改 → 返回受影响行数 int executeUpdate() // 批量执行(批量增删改) void addBatch() // 添加批处理任务 int[] executeBatch() // 执行批量任务 void clearBatch() // 清空批处理
5.4 完整增删改查示例
示例 1:查询(DQL)
// 1. 带 ? 占位符的SQL String sql = "select id,name,age from user where age > ?"; // 2. 创建预编译对象 PreparedStatement pstmt = conn.prepareStatement(sql); // 3. 给?赋值(索引从1开始) pstmt.setInt(1, 18); // 4. 执行查询 ResultSet rs = pstmt.executeQuery();
示例 2:新增(DML)
String sql = "insert into user(name,age) values(?,?)"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, "李四"); pstmt.setInt(2, 20); int rows = pstmt.executeUpdate(); // 返回影响行数 System.out.println("影响行数:" + rows);

  1. ResultSet 结果集对象(封装查询数据)

ResultSet用来接收select查询返回的表格数据,内部维护一个行指针(游标)。

6.1 核心原理
  • 游标默认指向第一行数据之前

  • 调用next()向下移动一行,有数据返回 true,无数据返回 false

6.2 核心方法
1)游标移动方法
boolean next() // 下移一行,常用 boolean previous() // 上移一行(滚动结果集) boolean first() // 移到第一行 boolean last() // 移到最后一行 void beforeFirst() // 回到初始位置
2)获取列数据 getXxx () 系列

两种取值方式:列索引 / 列名(推荐列名,可读性高)

// 按列索引(从1开始) int getInt(int columnIndex) String getString(int columnIndex) Date getDate(int columnIndex) // 按列名(推荐) int getInt(String columnLabel) String getString(String columnLabel) Date date = rs.getTimestamp("current_time"); Object getObject(String columnLabel) // 万能获取
6.3 遍历结果集标准写法
// 循环遍历每一行数据 while(rs.next()){ // 取列值 int id = rs.getInt("id"); String name = rs.getString("name"); int age = rs.getInt("age"); System.out.println(id + " " + name + " " + age); }
6.4 关闭资源顺序

顺序必须:ResultSet → PreparedStatement → Connection

if(rs != null) try{rs.close();}catch(Exception e){} if(pstmt != null) try{pstmt.close();}catch(Exception e){} if(conn != null) try{conn.close();}catch(Exception e){}

五、完整 JDBC 基础模板(可直接复用)

import java.sql.*; public class JdbcDemo { public static void main(String[] args) { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; try { // 1. 加载驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 2. 获取连接 String url = "jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC"; String user = "root"; String pwd = "123456"; conn = DriverManager.getConnection(url, user, pwd); // 3. 编写SQL + 创建预编译对象 String sql = "select * from user"; pstmt = conn.prepareStatement(sql); // 4. 执行查询,获取结果集 rs = pstmt.executeQuery(); // 5. 遍历结果 while (rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); System.out.println(id + " " + name); } } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } finally { // 6. 释放资源 try { if (rs != null) rs.close(); if (pstmt != null) pstmt.close(); if (conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }