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

Java 資料庫連線工具類實作詳解(含連線池與定時查詢)

     編輯:Java 相關知識

前言

在 Java 企業級開發中,資料庫連線管理是核心基礎設施之一。本文詳細解析一個功能完整的 DBUtil 工具類,涵蓋連線池建立、SQL 執行與查詢、結果集轉換、連線釋放以及防止連線逾時的定時查詢機制。程式碼基於 Apache Commons DBCP、DbUtils 與 Pool 元件,適合作為專案基礎設施參考。

核心依賴

  • commons-dbcp-1.4.jar
  • commons-dbutils-1.3.jar
  • commons-pool-1.5.4.jar

依賴包下載:java-db-dependency

類架構設計

DBUtil 採用單例模式管理連線池,主要職責包括:

  1. 連線池生命週期管理:啟動、關閉、獲取連線
  2. SQL 統一入口:提供 execute、query 多載方法
  3. 結果集轉換:將 ResultSet 轉為 List<Map<String, Object>>
  4. 定時保活機制:內部 QueryThread 每 2 分鐘執行 select 1 防止連線被資料庫斷開

關鍵原始碼解析

1. 建構子與連線池初始化

public DBUtil(String dri, String url, String userName, String password, String poolName) {
    this.dri = dri;
    this.url = url;
    this.username = userName;
    this.password = password;
    this.poolName = poolName;
}

參數說明:

  • dri:JDBC 驅動全類名(如 com.mysql.jdbc.Driver)
  • url:資料庫連線字串
  • poolName:連線池名稱,同一 Web 容器內不可重複

2. 連線池啟動邏輯

private void StartPool() {
    try {
        Class.forName(dri);
    } catch (ClassNotFoundException e1) { e1.printStackTrace(); }
    
    if (connectionPool != null) ShutdownPool();
    
    connectionPool = new GenericObjectPool(null);
    ConnectionFactory cf = new DriverManagerConnectionFactory(url, username, password);
    PoolableConnectionFactory pcf = new PoolableConnectionFactory(
        cf, connectionPool, null, "SELECT 1", false, true);
    
    Class.forName("org.apache.commons.dbcp.PoolingDriver");
    PoolingDriver driver = (PoolingDriver) DriverManager
        .getDriver("jdbc:apache:commons:dbcp:");
    driver.registerPool(poolName, pcf.getPool());
    
    // 啟動定時查詢執行緒
    queryThread = new QueryThread(this);
    queryThread.start();
}

關鍵點:

  • 使用 GenericObjectPool 作為連線池實作
  • 驗證查詢設為 SELECT 1,false, true 表示不檢查連線是否唯讀、但會測試連線有效性
  • 向 PoolingDriver 註冊連線池,後續透過 jdbc:apache:commons:dbcp:{poolName} 獲取連線

3. 統一 SQL 執行與查詢入口

// 執行更新類 SQL
public int execute(String sql) throws Exception {
    Connection conn = getConnection();
    try {
        QueryRunner qr = new QueryRunner();
        return qr.update(conn, sql);
    } finally { Close(conn); }
}

// 查詢(無參數)
public List<Map<String, Object>> query(String sql) throws SQLException {
    Connection conn = getConnection();
    try {
        QueryRunner qr = new QueryRunner();
        return qr.query(conn, sql, new MapListHandler());
    } finally { Close(conn); }
}

// 查詢(帶參數)
public List<Map<String, Object>> query(String sql, Object param) throws SQLException {
    Connection conn = getConnection();
    try {
        QueryRunner qr = new QueryRunner();
        return (List<Map<String, Object>>) qr.query(conn, sql, param, new MapListHandler());
    } catch (SQLException e) { e.printStackTrace(); }
    finally { Close(conn); }
    return null;
}

設計亮點:

  • 統一使用 QueryRunner 簡化 JDBC 模板代碼
  • MapListHandler 自動將每行結果映射為 Map<String, Object>
  • finally 區塊確保連線歸還池中

4. 定時保活執行緒

class QueryThread extends Thread {
    private DBUtil dbUtil;
    private boolean startQuery = true;
    
    public void run() {
        while (true) {
            try {
                if (startQuery) dbUtil.query("select 1");
            } catch (Exception e) { e.printStackTrace(); }
            finally {
                try { Thread.sleep(120000); } // 2 分鐘
                catch (InterruptedException e) { e.printStackTrace(); }
            }
        }
    }
    public void setStartQuery(boolean flag) { this.startQuery = flag; }
}

機制說明:

  • 每 120 秒發送一次 select 1,防止資料庫因閒置超時切斷連線
  • 連線池關閉時透過 setStartQuery(false) 停止執行緒

使用範例

// 初始化
DBUtil db = new DBUtil(
    "com.mysql.jdbc.Driver",
    "jdbc:mysql://127.0.0.1:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8",
    "root", "password", "mypool"
);

// 查詢
List<Map<String, Object>> list = db.query("SELECT * FROM users WHERE id = ?", 1);

// 更新
int rows = db.execute("UPDATE users SET name = ? WHERE id = ?", new Object[]{"Tom", 1});

注意事項與改進建議

  • 版本老舊:DBCP 1.4 已停止維護,建議升級至 HikariCP 或 DBCP 2.x
  • 例外處理:部分 catch 僅列印堆疊,生產環境應拋出或記錄日誌
  • 執行緒安全:getConnection() 加 synchronized,高併發下可能成為瓶頸
  • 資源洩漏風險:Close() 先 conn.close() 再 DbUtils.closeQuietly(),順序可調整

總結

此 DBUtil 展示了傳統 Java 專案中資料庫存取層的典型封裝方式,涵蓋連線池管理、SQL 執行、結果映射與連線保活等核心功能。雖然依賴的庫版本較舊,但其設計思路對理解連線池原理、DbUtils 使用及防止連線逾時策略仍有參考價值。現代專案建議採用 HikariCP + MyBatis/JdbcTemplate 等成熟框架替代。

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