【MySQL】JDBC
一、什么是JDBC
JDBC(Java DataBase Connectivity)是Java语言中用于连接和操作数据库的标准API(应用程序接口)。它提供了一组类和接口(只定义了方法,没有具体的实现),允许Java程序与各种关系型数据库(如MySQL、Oracle、PostgreSQL等)进行交互,执行SQL语句并处理结果。
如果Java要访问不同的数据库,就要根据数据库的协议进行代码的开发。Java中只定义了用于连接和操作数据的接口,JDBC具体的实现由数据库厂商完成
回顾客户端操作数据库的过程,主要分为以下几步:
1.连接到数据库服务 | getConnection |
2.发送SQL语句 | query |
3.得到返回结果并显示 | resultSet |
4.关闭连接 | close |
对于Java程序员来说,只需要调用JDBC的方法就可以完成数据库的具体操作
可以参考官方文档:MySQL :: MySQL Connector/J 发行说明 :: MySQL Connector/J 9.4.0 中的更改(2025-07-22,正式发布)https://dev.mysql.com/doc/relnotes/connector-j/en/news-9-4-0.html
二、使用JDBC
2.1 创建 MAVEN 工程并配置依赖
配置依赖
依赖仓库:Maven Repository: Search/Browse/Explore
在仓库中搜索MySQL
选择版本 8.0.33
复制代码到 pom.xml 文件中
在右上角加载依赖
2.2 使用 DriverManager 建立连接
1、加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
2、创建连接
//MySQL数据连接的URL参数格式如下:
jdbc:mysql://服务器地址:端口/数据库名?参数名=参数值,账号,密码
3、创建 Statement 对象,Statement对象是Java数据库连接(JDBC)的核心组件之一,它用于向数据库发送SQL语句以执行各种数据库操作。
Statement statement = connection.createStatement();
4、定义SQL语句
这里以查询为例
String sql = "select id,sn,name from student";
5、执行SQL获取结果
这里根据不同的sql语句需要使用不同的方法,例如与修改的sql语句就使用 executeUpdate
ResultSet resultSet = statement.executeQuery(sql);
6、遍历结果集,获取数据行
//6.遍历结果集,获取数据行. resultSet.next()返回一个boolean值,true表示有下一条记录while (resultSet.next()){//每进入一次循环表示读取了一行新记录//根据ID列的值,根据列的数据类型调用不同的方法//除了ID列还可以使用列标签来访问//int id = resultSet.getInt("id")int id = resultSet.getInt(1);//依次获取其他列的值int sn = resultSet.getInt(2);String name = resultSet.getString(3);//打印结果System.out.println(MessageFormat.format("学生编号={0} 学号={1} 姓名={2}",id,sn,name));}
7、释放资源
这里将释放资源放在finally处,就需要将变量定义在 try 外。且释放资源需要按照使用时相反的顺序进行释放
try {if(resultSet != null){resultSet.close();}} catch (SQLException e) {throw new RuntimeException(e);}try {if(statement != null){statement.close();}} catch (SQLException e) {throw new RuntimeException(e);}try {if(connection != null){connection.close();}} catch (SQLException e) {throw new RuntimeException(e);}
原数据表
运行结果:
完整代码:
import java.sql.*;
import java.text.MessageFormat;public class demo {public static void main(String[] args) throws SQLException {Connection connection = null;Statement statement = null;ResultSet resultSet = null;try {//1.加载数据库厂商提供的驱动,MySQL的JAR包就和JAVA环境建立了关系Class.forName("com.mysql.cj.jdbc.Driver");//2.建立数据库连接connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/stu?" +" user=root&password=root&useUnicode=true&characterEncoding=UTF-8","root","root");//3.创建Statement对象statement = connection.createStatement();//4.定义SQL语句String sql = "select id,sn,name from student";//5.执行SQL获取结果resultSet = statement.executeQuery(sql);//6.遍历结果集,获取数据行. resultSet.next()返回一个boolean值,true表示有下一条记录while (resultSet.next()){//每进入一次循环表示读取了一行新记录//根据ID列的值,根据列的数据类型调用不同的方法int id = resultSet.getInt(1);//依次获取其他列的值int sn = resultSet.getInt(2);String name = resultSet.getString(3);//打印结果System.out.println(MessageFormat.format("学生编号={0} 学号={1} 姓名={2}",id,sn,name));}} catch (ClassNotFoundException e) {throw new RuntimeException(e);} catch (SQLException e) {throw new RuntimeException(e);}finally {//依次释放资源try {if(resultSet != null){resultSet.close();}} catch (SQLException e) {throw new RuntimeException(e);}try {if(statement != null){statement.close();}} catch (SQLException e) {throw new RuntimeException(e);}try {if(connection != null){connection.close();}} catch (SQLException e) {throw new RuntimeException(e);}}}
}
这种连接方式存在一个弊端,SQL注入
三、SQL注入
3.1 SQL注入原理
SQL注入(SQL Injection)是一种常见的网络安全攻击技术,攻击者通过在应用程序的输入字段中插入恶意的SQL代码,欺骗数据库执行非预期的操作。这种攻击通常发生在未对用户输入进行充分过滤或验证的Web应用程序中。
使用正常语句进行查询,可以正常获取结果
修改查询语句为特殊字符构成,修改了原始SQL语句的逻辑,也能获取到表数据,这种就称作SQL注入
在DriverManager连接中通过 String 创建了SQL语句,现在修改成手动输入参数来测试SQL注入
这里可以完成正常的查询任务
再尝试使用特殊字符进行查询可以看到提示了报错,因为做了一些对特殊字符的过滤
但是由于过滤的不够充分依旧可以通过一些特殊字符串来获取到结果
3.2 解决SQL注入
为了防止上述问题带来的不利影响,可以使用 DataSource 来建立连接
配置 DataSource
// 定义MySQL数据源对象MysqlDataSource mysqlDataSource = new MysqlDataSource();// 设置数据库的连接串mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/stu?user=root&password=root&useUnicode=true&characterEncoding=UTF-8");// 设置用户名mysqlDataSource.setUser("root");// 设置密码mysqlDataSource.setPassword("123456");// 定义JDBC的数据源对象DataSource dataSource = mysqlDataSource;
获取连接
//声明数据库连接对象Connection connection = null;try {// 获取数据库连接connection = dataSource.getConnection();} catch (SQLException e) {throw new RuntimeException(e);}
使用 PreparedStatement 对SQL代码进行预处理
PreparedStatement 是 Java JDBC 中用于执行预编译 SQL 语句的接口,通过占位符(?
)绑定参数,避免字符串拼接导致的 SQL 注入风险。
# 将输入的参数直接替换到?处
select id,sn,name from student where name = '?';
String sql = "select id,sn,name from student where name = ?";
使用 statement 获取 sql 预处理对象
statement = connection.prepareStatement(sql);
// 用输入数据替换占位符(使用对应的数据类型),传入两个参数分别是?的id(从1开始)和值
statement.setString(1,inputName);
最后使用 ResultSet 来接收 sql 的执行结果
ResultSet resultSet = statement.executeQuery();
后续则和 DriverManager 一样,遍历结果集,打印,释放,最后查询结果
再输入同样的字符就无法查出表数据了
四、代码简化
从上面的代码中不难发现,有许多重复的地方,就可以通过一个类来定义,再用几个方法来连接、释放资源
package utils;import com.mysql.cj.jdbc.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;public class DBUtil {// 定义一个数据源对象private static DataSource dataSource;// 定义URLprivate static String URL = "jdbc:mysql://127.0.0.1:3306/stu?user=root&password=root&useUnicode=true&characterEncoding=UTF-8";// 定义用户名private static String USER = "root";// 定义密码private static String PASSWORD = "root";// 在类加载时初始化DataSource对象static {MysqlDataSource mysqlDataSource = new MysqlDataSource();mysqlDataSource.setURL(URL);mysqlDataSource.setUser(USER);mysqlDataSource.setPassword(PASSWORD);dataSource = mysqlDataSource;}// 构造方法私有化private DBUtil(){}/*** 获取数据库连接* @return* @throws SQLException*/public static Connection getConnection() throws SQLException {return dataSource.getConnection();}/*** 释放资源* @param resultSet* @param statement* @param connection*/public static void close(ResultSet resultSet, Statement statement,Connection connection){if(resultSet != null){try {resultSet.close();} catch (SQLException e) {throw new RuntimeException(e);}}if(statement != null){try {statement.close();} catch (SQLException e) {throw new RuntimeException(e);}}if(connection != null){try {connection.close();} catch (SQLException e) {throw new RuntimeException(e);}}}
}
五、DriverManager 和 DataSource 的区别
DriverManager 是 JDBC 中传统的数据库连接管理类,通过静态方法 getConnection()
建立与数据库的连接。它依赖于已注册的 JDBC 驱动程序,每次调用时会直接创建一个新的物理连接。这种方式简单易用,但缺乏连接池支持,频繁创建和关闭连接会导致性能问题。
DataSource 是 JDBC 2.0 引入的接口,提供了更灵活的连接管理机制。它支持连接池(如 HikariCP、DBCP),通过复用连接显著提升性能。DataSource 的实现类可以配置连接参数(超时时间、最大连接数等),适合企业级应用,尤其在高并发场景下表现更优。