MySQL之JDBC编程用法及说明
作者:重生之我是Java开发战士
文章介绍了JDBC的概念、特点和工作流程,提供了开发环境的准备工作,并详细讲解了JDBC的核心API,包括DriverManager、DataSource、Connection、Statement、PreparedStatement和ResultSet,此外,还讨论了SQL注入的问题及解决方案,并给出了完整代码示例
一、什么是 JDBC?
JDBC(Java Data Base Connectivity) 是 Java 提供的一套数据库操作接口标准,用来统一连接数据库、发送 SQL、处理结果。
特点:
- 面向接口编程,不关心底层数据库类型
- 切换数据库只需要换驱动包
- 是所有 ORM 框架(MyBatis、Hibernate)的底层基础
JDBC 的核心作用
- 建立数据库连接
- 发送 SQL 语句
- 接收并处理执行结果
- 关闭资源
JDBC 工作流程
正常来说,访问数据库的重要步骤如下,JDBC也提供了这些接口:
- 确定数据库服务器的地址和端口号(数据源)
- 建立连接,确定用户名,密码(数据库连接)
- 发送要执行的SQL(执行对象)
- 接收返回结果(结果集)
- 关闭连接(释放资源,关闭连接)
数据库厂商提供了JDBC具体的实现类,Java程序员只需要利用接口来写程序。
加载驱动 → 建立连接 → 创建 Statement → 执行 SQL → 处理结果 → 释放资源
二、开发环境准备(Maven 项目)
Maven类似于应用商店,在maven仓库中维护了所有Java工程所用到的依赖。maven仓库是国外的,可以用阿里的镜像。
1. 配置 Maven 阿里云镜像
加速依赖下载,在 settings.xml 的 <mirrors> 中加入:
<mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>
2. 引入 MySQL 驱动依赖
pom.xml:
<dependencies>
<!-- MySQL 8.x 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
三、JDBC 核心 API
1. DriverManager(传统连接)
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection= DriverManager.getConnection(url, user, password);
Driver类(驱动类)

2. DataSource(连接池)
DataSource通过一个连接池去管理很多个连接,当需要执行sql时拿出一个空的连接,用完返还给连接池。是更高效、支持连接复用,企业开发标准用法
MysqlDataSource dataSource = new MysqlDataSource(); dataSource.setURL(url); dataSource.setUser(user); dataSource.setPassword(password);
DriverManager VS DataSource
DriverManagergetConnection每次获取的是一个物理连接,每执行一次都会打开一个会话窗口,新建连接,用完销毁,性能低Datasourse一个连接可以执行很多SQL,直到关闭数据源。连接可复用,关闭只是归还,性能极高
3. Connection(连接对象)
代表一次数据库会话,用于创建 Statement。
4. Statement(执行对象)
- Statement:静态 SQL,存在 SQL 注入风险
- PreparedStatement:预编译 SQL,解决sql注入问题
- CallableStatement:执行存储过程
5. ResultSet(结果集)
封装 select 查询结果,用 next() 遍历,getXXX(列名/下标) 取值。
四、SQL 注入
什么是 SQL 注入?
用户输入恶意字符串,破坏原有 SQL 逻辑,实现越权查询/删改数据。
示例:
select * from student where name = '' or/**/1=1;#' and class_id=1
直接查出所有数据:

解决方案
PreparedStatement + 占位符 ?
Statement执行静态的sql语句,PreparedStatement可以预处理sql执行对象。参数会被安全转义,从根本杜绝注入。
五、完整代码
功能:根据 name 查询学生
基础版
package org.daisy;
import java.sql.*;
import java.text.MessageFormat;
import java.util.Scanner;
public class demo01_DriverManager {
static Scanner in = new Scanner(System.in);
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1. 加载数据库厂商提供的驱动
// "com.mysql.cj.jdbc.Driver" 通过完全限定名加载指定的类到JVM
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 建立连接
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test20260422?characterEncoding=utf8" +
"&allowPublicKeyRetrieval=true&useSSL=false", "root", "pullmecloser00");
//3. 创建statement对象
//sql语句通过connection发送
Statement statement = connection.createStatement();
//4. 定义sql语句
System.out.println("input name:");
String name = in.nextLine();
String sql = "select studentID,sn,name,mail,classID from student where name ='"+name+"';";
//5. 执行sql语句,获取结果集
ResultSet resultSet = statement.executeQuery(sql);
//6. 遍历结果集
// resultSet.next() 如果有下一条数据就返回true
while(resultSet.next()){
//获取学生ID,sql中的int对应Java中的int
int stuId = resultSet.getInt(1);
String stuSn = resultSet.getString(2);
String stuName = resultSet.getString(3);
String stuMail = resultSet.getString(4);
String stuClassId = resultSet.getString(5);
System.out.println(MessageFormat.format(
"学生编号 = {0},学号 = {1},学生姓名 = {2},邮箱 = {3},班级 = {4}",
stuId,stuSn,stuName,stuMail,stuClassId)
);
}
//7. 释放资源,关闭连接
resultSet.close();
statement.close();
connection.close();
}
}
DataSourse , Preparement 优化
package org.daisy;
import com.mysql.cj.jdbc.MysqlDataSource;
import javax.sql.*;
import java.text.MessageFormat;
import java.util.Scanner;
public class demo02_DataSource {
static Scanner in = new Scanner(System.in);
public static void main(String[] args) throws SQLException {
// 定义mysql数据源对象
MysqlDataSource mysqlDataSource = new MysqlDataSource();
//设置数据库连接串,用户名,密码
mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/test20260422?characterEncoding=utf8" +
"&allowPublicKeyRetrieval=true&useSSL=false");
mysqlDataSource.setUser("root");
mysqlDataSource.setPassword("pullmecloser00");
//定义jdbc数据源对象
DataSource dataSource = mysqlDataSource;
//1. 通过数据源获取数据库连接
Connection connection = dataSource.getConnection();
//2. 获取预处理sql执行对象
//定义要执行的sql语句
String sql = "select studentID,sn,name,mail,classID from student where name = ?";
//sql执行对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//用户输入查询信息
System.out.println("input name:");
String name = in.nextLine();
//3. 用真实值来替换占位符
//序号1对应第一个占位符
preparedStatement.setString(1,name);
//4. 执行sql,获取结果
//结果集对象
ResultSet resultSet = preparedStatement.executeQuery();
//遍历结果
while(resultSet.next()){
//获取学生ID,sql中的int对应Java中的int
int stuId = resultSet.getInt(1);
String stuSn = resultSet.getString(2);
String stuName = resultSet.getString(3);
String stuMail = resultSet.getString(4);
String stuClassId = resultSet.getString(5);
System.out.println(MessageFormat.format(
"学生编号 = {0},学号 = {1},学生姓名 = {2},邮箱 = {3},班级 = {4}",
stuId,stuSn,stuName,stuMail,stuClassId)
);
}
//5. 关闭资源,释放连接
resultSet.close();
preparedStatement.close();
connection.close();
}
}
把建立连接和关闭资源封装成对象
DBUtil类
package org.daisy.DBUtil;
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 {
/**
* 构造方法私有化,禁止其他类创建DBUtil对象,是单例模式的一个重要特征
*/
private DBUtil(){}
//数据源
private static DataSource dataSource = null;
//连接串,用户名,密码
private static String URL = "jdbc:mysql://127.0.0.1:3306/test20260422?characterEncoding=utf8" +
"&allowPublicKeyRetrieval=true&useSSL=false";
private static String user = "root";
private static String password = "pullmecloser00";
//类加载到JVM时,执行数据源的初始化
static {
MysqlDataSource mysqlDataSource = new MysqlDataSource();
mysqlDataSource.setURL(URL);
mysqlDataSource.setUser(user);
mysqlDataSource.setPassword(password);
dataSource = mysqlDataSource;
}
/**
* 获取数据库连接
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
/**
* 释放资源,关闭连接
* @param resultSet
* @param statement
* @param connection
* @throws SQLException
*/
public static void close(ResultSet resultSet, Statement statement,Connection connection) throws SQLException {
if(resultSet!=null)
resultSet.close();
if(statement!=null)
statement.close();
if(connection!=null)
connection.close();
}
}
Insert类
package org.daisy;
import org.daisy.DBUtil.DBUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
public class demo03_Insert {
static Scanner in = new Scanner(System.in);
public static void main(String[] args) throws SQLException {
//1. 获取数据库连接
Connection connection = DBUtil.getConnection();
//2. 定义sql
String sql = "insert student (sn,name,mail,classID) values (?,?,?,?)";
//3. 定义预处理对象
PreparedStatement statement = connection.prepareStatement(sql);
//4. 用真实数据填充占位符
System.out.println("input sn:");
String sn = in.nextLine();
System.out.println("input name:");
String name = in.nextLine();
System.out.println("input mail:");
String mail = in.nextLine();
System.out.println("input classId:");
String classId = in.nextLine();
statement.setString(1,sn);
statement.setString(2,name);
statement.setString(3,mail);
statement.setString(4,classId);
//5. 执行并判断 executeUpdate返回结果是受影响的行数
int row = statement.executeUpdate();
if(row == 1)
System.out.println("insert successfully");
else
System.out.println("insert fail");
//6. 关闭资源
DBUtil.close(null,statement,connection);
}
}
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
