JDBC 基础入门

JDBC(Java Database Connectivity)是 Java 访问数据库的标准接口,它允许开发者通过统一的 API 连接不同类型的数据库。本文将从基础概念入手,详细讲解 JDBC 的核心功能,并通过实例演示如何在项目中使用。

一、JDBC 架构与核心组件

JDBC 架构分为两层:

  • 应用层:Java 代码通过 JDBC API 发送 SQL 语句
  • 驱动层:JDBC 驱动程序负责与具体数据库通信

核心组件包括:

  • DriverManager:管理数据库驱动程序
  • Connection:表示与数据库的连接
  • Statement/PreparedStatement:执行 SQL 语句
  • ResultSet:处理查询结果

二、数据库连接详解

建立数据库连接的步骤如下:

  1. 加载数据库驱动:不同数据库需要不同的驱动类
  2. 创建连接 URL:包含数据库类型、地址、端口等信息
  3. 获取连接对象:通过 DriverManager.getConnection() 方法

以下是连接 MySQL 数据库的示例代码:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JdbcConnectionExample {
    public static void main(String[] args) {
        // 数据库连接信息
        String url = "jdbc:mysql://localhost:3306/mydatabase";
        String username = "root";
        String password = "password";
        
        // 尝试资源语句自动关闭连接
        try (Connection connection = DriverManager.getConnection(url, username, password)) {
            System.out.println("数据库连接成功!");
            // 后续操作...
        } catch (SQLException e) {
            System.err.println("连接失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

连接 URL 格式说明

  • jdbc:mysql://:MySQL 数据库协议
  • localhost:3306:数据库服务器地址和端口
  • mydatabase:要连接的数据库名称

三、使用 PreparedStatement 执行 SQL

PreparedStatement 是防止 SQL 注入的关键工具,它通过预编译 SQL 语句并使用参数占位符来提高安全性和性能。

示例:插入数据

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class PreparedStatementExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydatabase";
        String username = "root";
        String password = "password";
        
        // SQL 插入语句,使用 ? 作为参数占位符
        String sql = "INSERT INTO users (name, age, email) VALUES (?, ?, ?)";
        
        try (Connection conn = DriverManager.getConnection(url, username, password);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            
            // 设置参数值
            pstmt.setString(1, "张三");
            pstmt.setInt(2, 25);
            pstmt.setString(3, "[email protected]");
            
            // 执行更新
            int rowsInserted = pstmt.executeUpdate();
            if (rowsInserted > 0) {
                System.out.println("数据插入成功!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

防止 SQL 注入对比

普通 Statement:

// 存在 SQL 注入风险
String sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";

PreparedStatement:

// 安全的参数化查询
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
pstmt.setString(1, username);
pstmt.setString(2, password);

四、ResultSet 结果集处理

查询操作会返回 ResultSet 对象,它表示查询结果集。处理结果集的基本步骤:

  1. 遍历结果集:使用 next() 方法移动游标
  2. 获取字段值:根据字段类型使用 getInt()getString() 等方法

示例:查询并处理数据

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class ResultSetExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydatabase";
        String username = "root";
        String password = "password";
        
        // 查询语句
        String sql = "SELECT id, name, age, email FROM users WHERE age > ?";
        
        try (Connection conn = DriverManager.getConnection(url, username, password);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            
            // 设置查询参数
            pstmt.setInt(1, 20);
            
            // 执行查询
            ResultSet rs = pstmt.executeQuery();
            
            // 处理结果集
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                String email = rs.getString("email");
                
                System.out.printf("ID: %d, 姓名: %s, 年龄: %d, 邮箱: %s%n", id, name, age, email);
            }
            
            // 关闭结果集
            rs.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

结果集元数据
通过 ResultSetMetaData 可以获取结果集的结构信息:

ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();

for (int i = 1; i <= columnCount; i++) {
    System.out.println("列名: " + metaData.getColumnName(i));
    System.out.println("类型: " + metaData.getColumnTypeName(i));
}

五、资源管理与最佳实践

为避免资源泄漏,建议:

  1. 使用 try-with-resources:自动关闭 Connection、Statement 和 ResultSet
  2. 批量操作:使用 addBatch() 和 executeBatch() 提高性能
  3. 事务管理:通过 setAutoCommit(false) 和 commit() 管理事务

事务处理示例

try (Connection conn = DriverManager.getConnection(url, username, password)) {
    // 关闭自动提交,开启事务
    conn.setAutoCommit(false);
    
    try (PreparedStatement pstmt1 = conn.prepareStatement("UPDATE accounts SET balance = balance - ? WHERE id = ?");
         PreparedStatement pstmt2 = conn.prepareStatement("UPDATE accounts SET balance = balance + ? WHERE id = ?")) {
        
        // 执行第一个更新
        pstmt1.setDouble(1, 100.0);
        pstmt1.setInt(2, 1);
        pstmt1.executeUpdate();
        
        // 执行第二个更新
        pstmt2.setDouble(1, 100.0);
        pstmt2.setInt(2, 2);
        pstmt2.executeUpdate();
        
        // 提交事务
        conn.commit();
    } catch (SQLException e) {
        // 回滚事务
        conn.rollback();
        e.printStackTrace();
    }
}

六、总结

JDBC 是 Java 与数据库交互的基础,掌握以下关键点:

  1. 数据库连接流程:加载驱动 → 创建 URL → 获取连接
  2. 使用 PreparedStatement 执行安全的 SQL 操作
  3. 正确处理 ResultSet 结果集
  4. 合理管理数据库资源和事务

通过本文的示例,你可以构建基本的数据库应用程序。在实际开发中,还可以考虑使用数据库连接池(如 HikariCP)和 ORM 框架(如 Hibernate)来简化数据库操作。

你可能感兴趣的:(Java数据库编程,数据库,java)