本文涵盖JDBC 概述、开发步骤、核心 API、增删改查、工具类封装、SQL 注入漏洞与解决的内容。
一、JDBC 的概述
1. JDBC 是什么
- JDBC:Java DataBase Connectivity,Java 数据库连接
- 目的:使用 Java 代码操作数据库
- 必须遵循 JDBC 规范才能操作数据库
2. JDBC 的规范
- JDBC 是一套接口规范
- 实现类由各数据库厂商提供
- 只需掌握 JDBC 接口与方法即可通用操作数据库
3. 驱动(数据传输桥梁)
- 驱动就是数据库厂商提供的实现类
- 使用 MySQL 必须导入驱动 jar 包:
mysql-connector-java-5.1.13-bin.jar
4. JDBC 开发入门步骤
- 加载驱动
- 获取连接
- 执行 SQL 语句
- 处理结果集(查询)
- 释放资源
二、JDBC
1. MySQL 准备:创建数据库与表
-- 创建数据库
create database jdbcdemo;
use jdbcdemo;
-- 创建用户表
create table t_user(
id int primary key auto_increment,
username varchar(30),
password varchar(30),
email varchar(30)
);
-- 插入测试数据
insert into t_user values (null,'aaa','123','aaa@163.com');
insert into t_user values (null,'bbb','456','bb@163.com');
insert into t_user values (null,'ccc','789','ccc@163.com');
2. 需求
查询t_user表所有数据并输出到控制台
3. 标准开发步骤
- 加载驱动,使用 DriverManager类
- 获取连接,返回 Connection 接口,说明连上了数据库的服务器
- 编写 SQL 语句
- 获取执行 SQL 的对象(Statement 接口)
- 查询返回结果封装到 ResultSet接口,遍历结果集
- 释放资源(调用 close ())
三、JDBC 相关接口和 API
1. DriverManager 类(驱动管理)
作用
- 加载驱动
- static void registerDriver(Driver driver)
- 参数:传入的真正的参数其实是MySQL 提供 Driver 的类
- 获取数据库连接
加载驱动
java
Class.forName("com.mysql.jdbc.Driver");
- 不推荐:
DriverManager.registerDriver(new Driver())- 过度依赖实现类
- 驱动被加载两次
获取连接
java
static Connection getConnection(String url, String user, String password)
URL 格式
java
jdbc:mysql://localhost:3306/数据库名
- jdbc:主协议
- mysql:子协议
- localhost:主机地址
- 3306:MySQL 默认端口
- 数据库名:要操作的库
本地简写
jdbc:mysql:///数据库名
示例:
java
Connection conn = DriverManager.getConnection("jdbc:mysql:///jdbcdemo", "root", "root");
2. Connection 接口(数据库连接)
- 代表数据库连接,资源稀有,用完必须释放
作用
- 获取执行 SQL 的对象
Statement createStatement()‐‐ 获取到Statement接口- PreparedStatement prepareStatement(String sql)
‐‐ 获取到 PreparedStatement 接口,对象非常重要的,防止SQL 注入的漏洞。
- 管理事务
setAutoCommit(boolean autoCommit):开启事务commit():提交事务rollback():回滚事务
3. Statement 接口(执行 SQL 语句)
- 用于执行 SQL 语句的对象
方法
- 查询 :
ResultSet executeQuery(String sql) - 增删改 :
int executeUpdate(String sql) - 批处理
addBatch(String sql):添加 SQL 到批处理clearBatch():清空批处理executeBatch():执行批处理
4. ResultSet 接口(结果集封装)
- 封装查询返回的表格数据
- 内部维护游标,默认指向第一行之前
- 调用
next()向下移动游标,移动到某一行,获取该行的数据 - 游标只能向下移动
获取数据方法
- 根据类型:
getInt()、getString()、getLong() - 通用:
getObject()(自行强转) - 两种取值方式
- getInt(int index) ‐‐ 通过下标值来取值,默认从 1 开始
- getInt(String s) ‐‐ 通过字段的名称来取值,比较常用的
5. 释放资源
- 连接对象必须释放
- 代码放在finally中保证执行
- 标准释放模板
java
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
四、JDBC 增删改查
- 目标:回顾 API 方法 + 封装工具类
JDBC 工具类编写步骤
- 在 src 目录创建
db.properties配置文件(key=value 格式) - 编写工具类加载配置、获取连接、统一释放资源
控制台登录案例步骤
- 导入 MySQL 驱动 jar 包
- 复制工具类与配置文件
- 编写 User 实体类(JavaBean)
- 实现登录功能
五、SQL 注入漏洞
1. 漏洞效果
已知用户名,输入任意密码都能登录成功
2. 漏洞产生条件
- 已知用户名
- 后台直接字符串拼接 SQL
3. 注入示例
用户名输入:aaa' or '1=1密码任意
拼接后 SQL:
select * from t_user where username = 'aaa' or '1=1' and password = 'xxx'
或:
aaa' -- '
拼接后注释掉后面条件
java
-- 原因
String sql = "select * from t_user where username = '"+username+"' and password =
'"+password+"'";
-- 测试SQL注入漏洞的时候,输入如下的值
aaa'or'1=1,密码任意的
String sql = "select * from t_user where username = 'aaa'or'1=1' and
password = 'sfsdfsds";
aaa'‐‐ ',密码也是任意的
String sql = "select * from t_user where username = 'aaa'‐‐ '' and password
= 'sfsdfsdfs";
-- 实就是拼接SQL语句
4. 解决 SQL 注入
使用PreparedStatement接口(Statement 子接口)
- 支持预编译 SQL
- 使用
?作为占位符 - SQL 先编译,再传参,参数不会改变 SQL 结构
步骤
- 编写带?的 SQL
java
String sql = "select * from t_user where username=? and password=?";
- 获取 PreparedStatement
java
PreparedStatement pstmt = conn.prepareStatement(sql);
- 给?赋值(下标从 1 开始)
java
pstmt.setString(1, username);
pstmt.setString(2, password);
- 执行(无参数)
- 查询:
pstmt.executeQuery() - 增删改:
pstmt.executeUpdate()
总结
- JDBC 是 Java 操作数据库的规范,由厂商提供驱动实现
- 核心 API:DriverManager、Connection、Statement、ResultSet
- 开发固定步骤:加载驱动→获取连接→执行 SQL→处理结果→释放资源
- Statement 存在 SQL 注入风险,开发优先使用 PreparedStatement