目录
4. 使用 PreparedStatement 防止 SQL 注入
JDBC(Java Database Connectivity)是 Java 提供的数据库访问技术,它允许 Java 程序通过 SQL 语句与数据库进行交互。通过 JDBC,开发者能够实现常见的数据库操作,如增、删、改、查等。在这篇文章中,我们将深入探讨如何使用 JDBC 连接数据库,并执行各种常见的数据库操作。
一、JDBC 简介
JDBC 是 Java 语言提供的标准接口,允许开发者与各种关系型数据库系统(如 MySQL、Oracle、SQL Server 等)进行交互。JDBC 本质上是一组 Java API,它定义了如何执行 SQL 语句、更新数据、查询结果等操作。
在 JDBC 中,我们主要通过以下几个步骤进行数据库操作:
- 加载数据库驱动:通过
Class.forName()
或使用数据源自动加载数据库驱动。- 建立连接:使用
DriverManager.getConnection()
获取数据库连接。- 执行 SQL 语句:使用
Statement
或PreparedStatement
执行 SQL 语句。- 处理结果集:通过
ResultSet
处理查询结果。- 关闭资源:关闭
Connection
、Statement
和ResultSet
等资源。
二、JDBC 环境准备
1. 添加 JDBC 驱动
首先,确保在你的 Java 项目中添加了适合你所使用数据库的 JDBC 驱动。如果你使用的是 Maven 构建工具,可以在 pom.xml
文件中加入依赖:
对于 MySQL 数据库:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.26</version> </dependency>
对于 Oracle 数据库,可能需要下载 .jar
文件并手动添加到项目的 lib
目录中。
2. 创建数据库
假设我们使用 MySQL 数据库,首先在数据库中创建一个简单的表 users
,该表包含 id
、name
和 age
三个字段。你可以通过以下 SQL 语句创建数据库和表:
CREATE DATABASE testdb; USE testdb; CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, age INT NOT NULL ); INSERT INTO users (name, age) VALUES ('Alice', 30), ('Bob', 25), ('Charlie', 35);
三、JDBC 编程步骤
1. 加载数据库驱动
在 Java 中连接数据库时,首先需要加载数据库驱动。在 JDBC 中,我们可以通过 Class.forName()
方法加载驱动类。对于 MySQL 数据库,驱动类是 com.mysql.cj.jdbc.Driver
。
try { Class.forName("com.mysql.cj.jdbc.Driver"); // 加载 MySQL 驱动 System.out.println("数据库驱动加载成功"); } catch (ClassNotFoundException e) { e.printStackTrace(); System.out.println("数据库驱动加载失败"); }
2. 获取数据库连接
连接数据库是通过 DriverManager.getConnection()
方法实现的。在获取连接时,我们需要提供数据库的 URL、用户名和密码。连接 URL 的格式通常如下:
jdbc:mysql://localhost:3306/testdb
代码示例:
String url = "jdbc:mysql://localhost:3306/testdb"; String user = "root"; // 数据库用户名 String password = "password"; // 数据库密码 Connection conn = null; try { conn = DriverManager.getConnection(url, user, password); System.out.println("数据库连接成功"); } catch (SQLException e) { e.printStackTrace(); System.out.println("数据库连接失败"); }
3. 创建 Statement 对象并执行 SQL
一旦获得数据库连接,就可以通过 Connection
对象创建 Statement
或 PreparedStatement
来执行 SQL 语句。我们来看一个查询操作的例子,查询 users
表中的所有用户信息:
String query = "SELECT * FROM users"; Statement stmt = null; ResultSet rs = null; try { stmt = conn.createStatement(); rs = stmt.executeQuery(query); while (rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); int age = rs.getInt("age"); System.out.println("ID: " + id + ", Name: " + name + ", Age: " + age); } } catch (SQLException e) { e.printStackTrace(); } finally { // 关闭资源 try { if (rs != null) rs.close(); if (stmt != null) stmt.close(); if (conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } }
4. 使用 PreparedStatement 防止 SQL 注入
PreparedStatement
是 Statement
的一种增强版,它可以提高执行效率并防止 SQL 注入。在执行带参数的 SQL 语句时,应该优先使用 PreparedStatement
。
例如,插入一个新用户的 SQL 语句:
String insertQuery = "INSERT INTO users (name, age) VALUES (?, ?)"; PreparedStatement pstmt = null; try { pstmt = conn.prepareStatement(insertQuery); pstmt.setString(1, "David"); // 设置第一个参数为 "David" pstmt.setInt(2, 40); // 设置第二个参数为 40 int rowsAffected = pstmt.executeUpdate(); System.out.println("插入成功,受影响的行数:" + rowsAffected); } catch (SQLException e) { e.printStackTrace(); } finally { try { if (pstmt != null) pstmt.close(); if (conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } }
5. 事务管理
在 JDBC 中,可以使用事务来确保多个数据库操作的原子性。默认情况下,JDBC 使用自动提交模式,但你可以禁用自动提交来手动管理事务。以下是一个使用事务的示例:
try { conn.setAutoCommit(false); // 禁用自动提交 String updateQuery1 = "UPDATE users SET age = 26 WHERE name = 'Bob'"; String updateQuery2 = "UPDATE users SET age = 36 WHERE name = 'Charlie'"; stmt = conn.createStatement(); stmt.executeUpdate(updateQuery1); stmt.executeUpdate(updateQuery2); conn.commit(); // 提交事务 System.out.println("事务提交成功"); } catch (SQLException e) { try { if (conn != null) { conn.rollback(); // 回滚事务 System.out.println("事务回滚"); } } catch (SQLException ex) { ex.printStackTrace(); } e.printStackTrace(); } finally { try { if (stmt != null) stmt.close(); if (conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } }
6. 异常处理和关闭资源
在 JDBC 编程中,异常处理非常重要,因为数据库操作可能会出现各种问题。我们可以使用 try-catch-finally
块来确保资源得到正确释放。所有的数据库连接、Statement
和 ResultSet
都应该在使用完毕后关闭。
四、完整示例
下面是一个完整的 JDBC 示例程序,包括连接数据库、查询、插入、更新、删除操作:
import java.sql.*; public class JDBCExample { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/testdb"; String user = "root"; String password = "password"; Connection conn = null; Statement stmt = null; ResultSet rs = null; try { conn = DriverManager.getConnection(url, user, password); stmt = conn.createStatement(); // 查询操作 String query = "SELECT * FROM users"; rs = stmt.executeQuery(query); while (rs.next()) { System.out.println("ID: " + rs.getInt("id") + ", Name: " + rs.getString("name") + ", Age: " + rs.getInt("age")); } // 插入操作 String insertQuery = "INSERT INTO users (name, age) VALUES ('Eve', 28)"; stmt.executeUpdate(insertQuery); // 更新操作 String updateQuery = "UPDATE users SET age = 29 WHERE name = 'Eve'"; stmt.executeUpdate(updateQuery); // 删除操作 String deleteQuery = "DELETE FROM users WHERE name = 'Eve'"; stmt.executeUpdate(deleteQuery); } catch (SQLException e) { e.printStackTrace(); } finally { try { if (rs != null) rs.close(); if (stmt != null) stmt.close(); if (conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }