Java JDBC 連接 MySQL 工具類:單例模式與資源釋放最佳實踐
完整代碼
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DBUtils {
// 數據庫連接配置
private static final String URL = "jdbc:mysql://localhost:3306/jdbc?characterEncoding=utf-8";
private static final String USER_NAME = "root";
private static final String PASSWORD = "123123";
// 單例模式
private static DBUtils instance = new DBUtils();
public static DBUtils getInstance() {
return instance;
}
// 私有構造器,防止外部實例化
private DBUtils() {}
/**
* 獲取數據庫連接
* @return Connection 對象,失敗返回 null
*/
public Connection getConn() {
Connection conn = null;
try {
// 1. 載入驅動 (JDBC 4.0+ 可省略,但保留兼容)
Class.forName("com.mysql.jdbc.Driver");
// 2. 建立連接
conn = DriverManager.getConnection(URL, USER_NAME, PASSWORD);
} catch (ClassNotFoundException e) {
System.err.println("MySQL JDBC Driver 未找到: " + e.getMessage());
e.printStackTrace();
} catch (SQLException e) {
System.err.println("數據庫連接失敗: " + e.getMessage());
e.printStackTrace();
}
return conn;
}
/**
* 統一釋放資源(按逆序:ResultSet → Statement → Connection)
* @param conn 連接對象
* @param pstmt 預編譯語句對象
* @param rs 結果集對象
*/
public void releaseRes(Connection conn, PreparedStatement pstmt, ResultSet rs) {
try {
if (rs != null) rs.close();
if (pstmt != null) pstmt.close();
if (conn != null) conn.close();
} catch (SQLException e) {
System.err.println("資源釋放異常: " + e.getMessage());
e.printStackTrace();
}
}
}
使用範例
public class UserDao {
public User findById(int id) {
DBUtils utils = DBUtils.getInstance();
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = utils.getConn();
String sql = "SELECT id, username, email FROM users WHERE id = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);
rs = pstmt.executeQuery();
if (rs.next()) {
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setEmail(rs.getString("email"));
return user;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
utils.releaseRes(conn, pstmt, rs);
}
return null;
}
}
核心設計要點
| 要點 | 說明 |
| 單例模式 | 私有構造器 + 靜態實例 + 靜態工廠方法,確保全局唯一配置入口。 |
| 資源釋放順序 | ResultSet → PreparedStatement → Connection(逆序),避免資源洩漏。 |
| 異常處理 | 捕獲具體異常,打印錯誤堆疊,返回 null 或拋出業務異常,不吞沒異常。 |
| 連接參數 | URL 含 characterEncoding=utf-8 防止中文亂碼;生產環境建議外部化配置(properties/YAML)。 |
| 驅動類 | com.mysql.jdbc.Driver (5.1.x) / com.mysql.cj.jdbc.Driver (8.0+)。 |
生產環境擴展建議
- 連接池:單連接無法支撐併發,必須接入 HikariCP / Druid / DBCP2。
- 配置外部化:URL、用戶、密碼、池參數置於
application.yml 或 db.properties。
- 重試機制:網路抖動時自動重試(指數退避)。
- 監控指標:活躍連接數、等待線程數、慢查詢統計。