在 Java 开发领域,JDBC(Java Database Connectivity)作为 Java 访问数据库的标准 API,是 Java 程序与各类关系型数据库进行交互的桥梁。
MyBatis 作为优秀的持久层框架,其底层本质是对 JDBC 的封装,因此透彻理解 JDBC 的执行过程,是深入掌握 MyBatis 原理的关键。下面,我们将深入剖析 JDBC 执行数据库操作的具体步骤。
一、加载数据库驱动
JDBC 规范定义了一系列接口,数据库厂商需实现这些接口,提供对应的驱动程序,以实现 Java 与自家数据库的交互。在开展数据库操作前,首要任务是加载对应的数据库驱动,常见的加载方式有以下两种:
-
通过
Class.forName()方法加载:这是早期广泛使用的加载方式,借助反射机制加载驱动类。以加载 MySQL 数据库驱动为例:Class.forName("com.mysql.cj.jdbc.Driver");执行该语句时,
JVM会查找并加载指定的驱动类,驱动类在加载过程中会自动向DriverManager注册,为后续获取数据库连接做好准备。 -
利用
Java的服务发现机制(SPI)加载:从Java 6开始,JDBC 4.0引入自动加载驱动机制。只要数据库驱动的JAR包位于类路径下,驱动类便会自动加载并注册到DriverManager,无需手动调用Class.forName()
二、建立数据库连接
完成驱动加载后,接下来需建立与数据库的连接。此步骤通过DriverManager.getConnection()方法实现,该方法需要传入数据库的 URL、用户名和密码:
String url = "jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC"; // 数据库连接URL,包含协议、主机地址、端口号、数据库名称及时间区设置
String username = "xxx"; // 数据库用户名
String password = "xxxx"; // 数据库密码
// 获取数据库连接对象
Connection connection = DriverManager.getConnection(url, username, password);
url格式因数据库而异,例如 MySQL 的格式为jdbc:mysql://主机:端口/数据库名?参数
三、创建执行对象
连接建立后,需要创建执行 SQL 语句的对象。JDBC 提供三种执行对象:
-
Statement:用于执行静态 SQL 语句Statement statement = connection.createStatement(); -
PreparedStatement(推荐):用于执行预编译 SQL 语句,可防止 SQL 注入并提高性能// 预编译SQL语句,使用占位符? String sql = "SELECT * FROM users WHERE age > ?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); // 设置参数,1表示第一个占位符,18为参数值 preparedStatement.setInt(1, 18); -
CallableStatement:用于执行存储过程CallableStatement callableStatement = connection.prepareCall("{call get_user_count(?)}"); callableStatement.registerOutParameter(1, Types.INTEGER);
四、执行 SQL 语句
创建执行对象后,使用相应方法执行 SQL 语句:
-
查询语句:使用
executeQuery()方法,返回ResultSet结果集ResultSet resultSet = preparedStatement.executeQuery(); -
更新语句:使用
executeUpdate()方法,返回受影响的行数int rowsAffected = preparedStatement.executeUpdate(); -
通用执行:使用
execute()方法,返回布尔值表示是否返回结果集boolean hasResultSet = statement.execute(sql);
五、处理查询结果
执行查询后,通过ResultSet遍历和处理结果集:
while (resultSet.next()) { // 移动到下一行,有数据返回true
int id = resultSet.getInt("id"); // 获取id列的值
String name = resultSet.getString("name"); // 获取name列的值
int age = resultSet.getInt("age"); // 获取age列的值
System.out.println("ID: " + id + ", Name: " + name + ", Age: " + age);
}
ResultSet提供多种getXXX()方法,根据列名或索引获取不同类型的数据
六、释放资源
按ResultSet → Statement → Connection顺序关闭连接,释放数据库资源。
// 关闭顺序:先打开的后关闭
resultSet.close();
preparedStatement.close();
connection.close();
为确保资源释放,通常将关闭操作放在finally块中。
完整代码示例
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JDBCQueryExample {
public static void main(String[] args) {
// 声明数据库连接和执行对象
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
// 一、加载数据库驱动(MySQL 8.0以上版本)
Class.forName("com.mysql.cj.jdbc.Driver");
// 二、建立数据库连接
String url = "jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC";
String username = "root";
String password = "123456";
connection = DriverManager.getConnection(url, username, password);
// 三、创建执行对象并设置参数
String sql = "SELECT * FROM users WHERE age > ?";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, 18); // 设置查询参数,年龄大于18
// 四、执行SQL语句
resultSet = preparedStatement.executeQuery();
// 五、处理查询结果
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
System.out.println("ID: " + id + ", Name: " + name + ", Age: " + age);
}
} catch (ClassNotFoundException e) {
// 处理驱动加载异常
System.err.println("找不到数据库驱动: " + e.getMessage());
} catch (SQLException e) {
// 处理SQL异常
System.err.println("数据库操作错误: " + e.getMessage());
} finally {
// 六、释放资源(确保资源被关闭,即使发生异常)
try {
if (resultSet != null) resultSet.close();
if (preparedStatement != null) preparedStatement.close();
if (connection != null) connection.close();
} catch (SQLException e) {
System.err.println("关闭资源错误: " + e.getMessage());
}
}
}
}

1053

被折叠的 条评论
为什么被折叠?



