上一節實現了基礎 JDBC 連接查詢,但存在硬編碼配置、資源釋放繁瑣、異常處理分散等問題。本節引入 DBUtility 工具類,實現配置外部化、連接獲取/關閉統一封裝、資源安全釋放,為後續連接池引入奠基。
db.properties# src/main/resources/db.properties jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.1:3306/emp?useUnicode=true&characterEncoding=utf8 jdbc.user=wonderq jdbc.password=root
優勢:環境差異化配置(dev/test/prod)無需改代碼,僅替換文件;敏感信息可接入配置中心加密管理。
package dao;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class DBUtility {
private static String driver;
private static String url;
private static String user;
private static String password;
// 靜態塊:類加載時一次性讀取配置、註冊驅動
static {
Properties props = new Properties();
try (InputStream is = DBUtility.class.getClassLoader().getResourceAsStream("db.properties")) {
if (is == null) throw new RuntimeException("db.properties not found in classpath");
props.load(is);
driver = props.getProperty("jdbc.driver");
url = props.getProperty("jdbc.url");
user = props.getProperty("jdbc.user");
password = props.getProperty("jdbc.password");
Class.forName(driver); // 註冊驅動
} catch (IOException | ClassNotFoundException e) {
throw new ExceptionInInitializerError(e);
}
}
// 獲取新連接
public static Connection openConnection() throws SQLException {
return DriverManager.getConnection(url, user, password);
}
// 安全關閉連接(吞掉異常,記錄日誌)
public static void closeConnection(Connection conn) {
if (conn != null) {
try { conn.close(); } catch (SQLException e) { System.err.println("關閉連接異常: " + e.getMessage()); }
}
}
// 通用資源關閉(ResultSet -> Statement -> Connection)
public static void closeAll(java.sql.ResultSet rs, java.sql.Statement stmt, Connection conn) {
if (rs != null) try { rs.close(); } catch (SQLException e) { /* ignore */ }
if (stmt != null) try { stmt.close(); } catch (SQLException e) { /* ignore */ }
closeConnection(conn);
}
}
package dao;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class EmpDAO {
public void findAll() {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = DBUtility.openConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT empno, ename, sal, hiredate FROM emp");
while (rs.next()) {
System.out.printf("%d, %s, %.2f, %s%n",
rs.getInt("empno"),
rs.getString("ename"),
rs.getDouble("sal"),
rs.getDate("hiredate"));
}
} catch (SQLException e) {
throw new RuntimeException("數據庫訪問異常", e);
} finally {
DBUtility.closeAll(rs, stmt, conn); // 一鍵安全釋放
}
}
public static void main(String[] args) {
new EmpDAO().findAll();
}
}
7369, SMITH, 800.00, 1980-12-17 7499, ALLEN, 1600.00, 1981-02-20 7521, WARD, 1250.00, 1981-02-22 7566, JONES, 2975.00, 1981-04-02 7654, MARTIN, 1250.00, 1981-09-28 7698, BLAKE, 2850.00, 1981-05-01 7782, CLARK, 2450.00, 1981-06-09 7788, SCOTT, 3000.00, 1987-04-19 7839, KING, 5000.00, 1981-11-17 7844, TURNER, 1500.00, 1981-09-08 7876, ADAMS, 1100.00, 1987-05-23 7900, JAMES, 950.00, 1981-12-03 7902, FORD, 3000.00, 1981-12-03 7934, MILLER, 1300.00, 1982-01-23
| 模式要素 | 體現位置 |
|---|---|
| 工廠模式 | openConnection() 封裝連接創建細節 |
| 單例/靜態工具 | DBUtility 無狀態,靜態方法全局可用 |
| 資源獲取即初始化 (RAII) | closeAll() 在 finally 統一釋放,防洩漏 |
| 配置解耦 | Properties 文件外部化,支援多環境部署 |
max_connections 導致服務不可用。👉 下一節將引入 Apache DBCP 連接池,徹底解決上述問題。