JDBC

Marimo_z
2025-04-16 / 0 评论 / 4 阅读 / 正在检测是否收录...

1. JDBC 概述

  • JDBC (Java Database Connectivity) 是 Java 提供的用于操作关系型数据库的标准 API。
  • 核心功能:连接数据库、执行 SQL、处理结果集。
  • 驱动类型

    • Type 1:JDBC-ODBC 桥接(已淘汰)。
    • Type 2:本地 API 驱动(如 Oracle OCI)。
    • Type 3:网络协议驱动(如旧版 MySQL Connector/J)。
    • Type 4:纯 Java 驱动(主流,如 mysql-connector-java)。

2. JDBC 核心接口与类

接口/类作用
DriverManager管理数据库驱动,建立连接。
Connection表示与数据库的会话。
Statement执行静态 SQL 语句(存在 SQL 注入风险)。
PreparedStatement预编译 SQL 语句(防注入,高效复用)。
CallableStatement调用存储过程。
ResultSet封装查询结果集。
ResultSetMetaData获取结果集的元信息(列名、类型等)。

3. JDBC 操作流程

  1. 加载驱动

    Class.forName("com.mysql.cj.jdbc.Driver"); // MySQL 驱动类
  2. 建立连接

    String url = "jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC";
    String user = "root";
    String password = "123456";
    Connection conn = DriverManager.getConnection(url, user, password);
  3. 创建 Statement

    Statement stmt = conn.createStatement(); // 静态 SQL
    PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users WHERE id=?"); // 预编译
  4. 执行 SQL

    • 查询

      ResultSet rs = stmt.executeQuery("SELECT * FROM users");
    • 更新(INSERT/UPDATE/DELETE)

      int rows = stmt.executeUpdate("DELETE FROM users WHERE age < 18");
  5. 处理结果集

    while (rs.next()) {
        int id = rs.getInt("id");
        String name = rs.getString("name");
        System.out.println(id + ": " + name);
    }
  6. 关闭资源

    rs.close(); 
    stmt.close(); 
    conn.close(); // 必须按顺序关闭(后开先关)

4. PreparedStatement 防止 SQL 注入

String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, userInputName);  // 参数索引从 1 开始
pstmt.setString(2, userInputPass);
ResultSet rs = pstmt.executeQuery();

5. 事务管理

try {
    conn.setAutoCommit(false); // 关闭自动提交
    // 执行多个 SQL 操作...
    conn.commit(); // 提交事务
} catch (SQLException e) {
    conn.rollback(); // 回滚事务
} finally {
    conn.setAutoCommit(true); // 恢复默认
}

6. 结果集元数据(动态处理未知表结构)

ResultSetMetaData meta = rs.getMetaData();
int columnCount = meta.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
    String columnName = meta.getColumnName(i);
    String columnType = meta.getColumnTypeName(i);
    System.out.println(columnName + " (" + columnType + ")");
}

7. 连接池(以 HikariCP 为例)

  1. 添加依赖

    <dependency>
        <groupId>com.zaxxer</groupId>
        <artifactId>HikariCP</artifactId>
        <version>5.0.1</version>
    </dependency>
  2. 配置与使用

    HikariConfig config = new HikariConfig();
    config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
    config.setUsername("root");
    config.setPassword("123456");
    config.setMaximumPoolSize(10); // 最大连接数
    
    try (HikariDataSource dataSource = new HikariDataSource(config);
         Connection conn = dataSource.getConnection()) {
        // 使用连接...
    }

8. 常见异常与解决

  • ClassNotFoundException: com.mysql.jdbc.Driver

    • 原因:未添加数据库驱动 JAR 包。
    • 解决:检查项目依赖或 Classpath。
  • SQLException: Connection refused

    • 原因:数据库服务未启动或网络不通。
    • 解决:检查数据库状态、端口及防火墙设置。
  • SQLSyntaxErrorException

    • 原因:SQL 语句语法错误。
    • 解决:打印 SQL 并手动验证。

9. 最佳实践

  1. 资源释放
    使用 try-with-resources 自动关闭资源(Java 7+):

    try (Connection conn = DriverManager.getConnection(url);
         PreparedStatement pstmt = conn.prepareStatement(sql);
         ResultSet rs = pstmt.executeQuery()) {
        // 操作数据...
    }
  2. 避免 SELECT *:
    明确指定查询字段,减少网络传输开销。
  3. 批量处理

    pstmt.addBatch(); // 添加批处理
    pstmt.executeBatch(); // 执行批处理

10. 总结

  • JDBC 是 Java 操作数据库的基石,需掌握核心接口与流程。
  • 优先使用 PreparedStatement 防注入,结合连接池提升性能。
  • 事务管理和资源释放是保证数据一致性和稳定性的关键。
1

评论 (0)

取消