首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java JDBC 連接 MySQL 完整實戰:從環境搭建到 CRUD 代碼模板

     編輯:Java 綜合教學

前置條件清單

  1. JDK 8+(配置 JAVA_HOME、Path)
  2. MySQL 5.7/8.0 服務運行中
  3. MySQL Connector/J 驅動 JAR(mysql-connector-java-8.0.33.jar 或 Maven 坐標)
  4. IDE(Eclipse/IDEA/VS Code)
  5. 建庫建表:

CREATE DATABASE jdbc_demo CHARSET utf8mb4;
USE jdbc_demo;
CREATE TABLE t_user (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100)
);
INSERT INTO t_user(username, email) VALUES ('alice','alice@example.com'),('bob','bob@example.com');

Maven 依賴(推薦)


<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.0.33</version>
</dependency>

非 Maven 專案:將 JAR 放入 WEB-INF/lib 或 Build Path。

完整 CRUD 代碼模板


import java.sql.*;
import java.util.*;

public class JdbcTemplate {
    // 配置常量
    private static final String URL = "jdbc:mysql://localhost:3306/jdbc_demo?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8";
    private static final String USER = "root";
    private static final String PASS = "123456";

    // 靜態塊載入驅動(Java 6+ SPI 機制可省略,保留兼容舊版本)
    static {
        try { Class.forName("com.mysql.cj.jdbc.Driver"); }
        catch (ClassNotFoundException e) { throw new ExceptionInInitializerError(e); }
    }

    // 獲取連接(生產環境請用連接池 HikariCP/Druid)
    private static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(URL, USER, PASS);
    }

    // ============ 查詢 ============
    public static List<Map<String, Object>> queryList(String sql, Object... params) {
        List<Map<String, Object>> result = new ArrayList<>();
        try (Connection conn = getConnection();
             PreparedStatement ps = conn.prepareStatement(sql)) {
            setParams(ps, params);
            try (ResultSet rs = ps.executeQuery()) {
                ResultSetMetaData md = rs.getMetaData();
                int cols = md.getColumnCount();
                while (rs.next()) {
                    Map<String, Object> row = new LinkedHashMap<>();
                    for (int i = 1; i <= cols; i++) {
                        row.put(md.getColumnLabel(i), rs.getObject(i));
                    }
                    result.add(row);
                }
            }
        } catch (SQLException e) { throw new RuntimeException(e); }
        return result;
    }

    public static Map<String, Object> queryOne(String sql, Object... params) {
        List<Map<String, Object>> list = queryList(sql, params);
        return list.isEmpty() ? null : list.get(0);
    }

    // ============ 增刪改 ============
    public static int executeUpdate(String sql, Object... params) {
        try (Connection conn = getConnection();
             PreparedStatement ps = conn.prepareStatement(sql)) {
            setParams(ps, params);
            return ps.executeUpdate();
        } catch (SQLException e) { throw new RuntimeException(e); }
    }

    // 批量執行
    public static int[] batchUpdate(String sql, List<Object[]> paramList) {
        try (Connection conn = getConnection();
             PreparedStatement ps = conn.prepareStatement(sql)) {
            conn.setAutoCommit(false);
            for (Object[] params : paramList) {
                setParams(ps, params);
                ps.addBatch();
            }
            int[] counts = ps.executeBatch();
            conn.commit();
            return counts;
        } catch (SQLException e) { throw new RuntimeException(e); }
    }

    // ============ 工具方法 ============
    private static void setParams(PreparedStatement ps, Object... params) throws SQLException {
        for (int i = 0; i < params.length; i++) {
            ps.setObject(i + 1, params[i]);
        }
    }

    // ============ Demo ============
    public static void main(String[] args) {
        // 查詢所有
        System.out.println("=== 所有用戶 ===");
        queryList("SELECT * FROM t_user").forEach(System.out::println);

        // 條件查詢
        System.out.println("\n=== ID=1 ===");
        System.out.println(queryOne("SELECT * FROM t_user WHERE id=?", 1));

        // 新增
        int inserted = executeUpdate("INSERT INTO t_user(username,email) VALUES(?,?)", "charlie", "charlie@test.com");
        System.out.println("\n新增行數:" + inserted);

        // 修改
        int updated = executeUpdate("UPDATE t_user SET email=? WHERE username=?", "new@alice.com", "alice");
        System.out.println("修改行數:" + updated);

        // 刪除
        int deleted = executeUpdate("DELETE FROM t_user WHERE username=?", "bob");
        System.out.println("刪除行數:" + deleted);
    }
}

關鍵最佳實踐

實踐理由
PreparedStatement 防注入參數化查詢,杜絕 SQL 拼接
try-with-resources 自動關閉Connection/Statement/ResultSet 實現 AutoCloseable,無需 finally
生產必上連接池頻繁創建銷毀連接極其昂貴,HikariCP 為首選
事務控制conn.setAutoCommit(false) → 操作 → commit()/rollback()
結果集映射手寫 RowMapper 或用 DbUtils/MyBatis 簡化
時區統一URL 帶 serverTimezone=Asia/Shanghai,避免時區跳坑

常見異常排查

異常原因解決
ClassNotFoundException: com.mysql.cj.jdbc.Driver驅動 JAR 未在 ClasspathMaven 依賴 / Build Path 添加 JAR
Communications link failureIP/端口/防火牆/MySQL 未啟用遠程檢查 bind-address=0.0.0.0、安全組、FLUSH PRIVILEGES
Public Key Retrieval is not allowedMySQL 8 默認 caching_sha2_passwordURL 加 allowPublicKeyRetrieval=true 或用戶改 mysql_native_password
SSL connection error驅動默認要求 SSLURL 加 useSSL=false(開發環境)

進階:HikariCP 連接池整合(3 行代碼)


HikariConfig config = new HikariConfig();
config.setJdbcUrl(URL);
config.setUsername(USER);
config.setPassword(PASS);
config.setMaximumPoolSize(20);
DataSource ds = new HikariDataSource(config);

// 後續直接 ds.getConnection(),其餘邏輯不變

總結

JDBC 核心四步:**載入驅動 → 獲取連接 → PreparedStatement 執行 → 釋放資源**。掌握 PreparedStatement 防注入、try-with-resources 自動關閉、**連接池** 這三大支柱,即可編寫健壯、高效的數據訪問代碼。生產項目請直接上 **MyBatis / MyBatis-Plus / JdbcTemplate** 等成熟框架,專注業務邏輯而非樣板代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved