封裝JDBC操作的工具類是Java項目基礎設施核心。本文提供一個生產就緒的DBConnect單例模式實現,涵蓋連接池準備、PreparedStatement參數綁定、事務控制、資源安全釋放等完整功能,並指出代碼中可優化之處。
database.properties外部化配置(驅動、URL、用戶、密碼)Statement與PreparedStatement雙模式setXxx方法鏈:String、Int、Boolean、Date、Long、Float、Bytes、Integer、ShortsetAutoCommit、commit、rollbackclearParameters、clearStmt、closeprivate DBConnect() {
init(); // 載入properties
try {
Class.forName(dbDriver);
conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword);
conn.setAutoCommit(true);
stmt = conn.createStatement();
} catch (Exception e) { logError(e); }
}
private void init() {
InputStream is = getClass().getResourceAsStream("/database.properties");
Properties props = new Properties();
props.load(is);
dbDriver = props.getProperty("driver", "com.mysql.jdbc.Driver");
dbUrl = props.getProperty("url", "jdbc:mysql://localhost/db?autoReconnect=true&useUnicode=true&characterEncoding=gbk");
dbUser = props.getProperty("username", "1111111");
dbPassword = props.getProperty("password", "111111");
}
public void prepareStatement(String sql) throws SQLException {
clearParameters();
prepstmt = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
}
public void setString(int index, String value) throws SQLException { prepstmt.setString(index, value); }
public void setInt(int index, int value) throws SQLException { prepstmt.setInt(index, value); }
public void setDate(int index, Date value) throws SQLException { prepstmt.setDate(index, value); }
// ... 其他類型同理
public ResultSet executePrepQuery() throws SQLException {
return prepstmt != null ? prepstmt.executeQuery() : null;
}
public int executePrepUpdate() throws SQLException {
return prepstmt != null ? prepstmt.executeUpdate() : 0;
}
private void clearParameters() {
try {
if (prepstmt != null) {
prepstmt.clearParameters();
prepstmt.close();
}
} catch (Exception ignored) {}
prepstmt = null;
}
public void close() {
try {
clearParameters();
clearStmt();
if (conn != null) conn.close();
} catch (SQLException ex) { logError(ex); }
}
| 問題 | 風險 | 建議 |
|---|---|---|
單例模式getInstance()每次new DBConnect() | 非真正單例,頻繁創建連接 | 改用雙重檢查鎖或枚舉單例,配合連接池 |
硬編碼默認密碼111111 | 安全隱患 | 移除默認值,啟動時強制檢查配置完整性 |
catch (Exception e) {}吞噬異常 | 調試困難,掩蓋根因 | 至少記錄日誌,拋出運行時異常 |
| 無連接池,每操作一連接 | 性能差,連接洩漏風險 | 集成HikariCP/Druid,DataSource注入 |
prepareStatement固定游標類型 | MySQL不支持TYPE_SCROLL_INSENSITIVE | 移除或根據數據庫動態適配 |
未實現AutoCloseable | 無法使用try-with-resources | 實現接口,簡化調用端資源管理 |
新項目建議直接使用:
若維護舊系統,請基於上述優化點重構DBConnect,最小化風險。