mysql mysql-connector-java 8.0.33
驅動類名差異:
com.mysql.jdbc.Drivercom.mysql.cj.jdbc.Driverpublic class JdbcUtil {
private static final String URL = "jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC&characterEncoding=utf8";
private static final String USER = "root";
private static final String PASSWORD = "123456";
private static final String DRIVER = "com.mysql.cj.jdbc.Driver"; // 8.x
static {
try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { throw new ExceptionInInitializerError(e); }
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(URL, USER, PASSWORD);
}
public static void close(Connection conn, Statement stmt, ResultSet rs) {
try { if (rs != null) rs.close(); } catch (SQLException ignore) {}
try { if (stmt != null) stmt.close(); } catch (SQLException ignore) {}
try { if (conn != null) conn.close(); } catch (SQLException ignore) {}
}
}
public ListqueryUsers() { String sql = "SELECT id, username, email FROM users WHERE status = ?"; List list = new ArrayList<>(); Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JdbcUtil.getConnection(); ps = conn.prepareStatement(sql); ps.setInt(1, 1); // 參數綁定,防注入 rs = ps.executeQuery(); while (rs.next()) { User u = new User(); u.setId(rs.getLong("id")); u.setUsername(rs.getString("username")); u.setEmail(rs.getString("email")); list.add(u); } } catch (SQLException e) { e.printStackTrace(); // 生產環境用日誌框架 } finally { JdbcUtil.close(conn, ps, rs); } return list; }
public void transfer(Long fromId, Long toId, BigDecimal amount) {
Connection conn = null;
try {
conn = JdbcUtil.getConnection();
conn.setAutoCommit(false); // 開啟事務
// 扣款
try (PreparedStatement ps = conn.prepareStatement("UPDATE account SET balance = balance - ? WHERE id = ?")) {
ps.setBigDecimal(1, amount);
ps.setLong(2, fromId);
ps.executeUpdate();
}
// 入賬
try (PreparedStatement ps = conn.prepareStatement("UPDATE account SET balance = balance + ? WHERE id = ?")) {
ps.setBigDecimal(1, amount);
ps.setLong(2, toId);
ps.executeUpdate();
}
conn.commit();
} catch (SQLException e) {
if (conn != null) try { conn.rollback(); } catch (SQLException ignore) {}
throw new RuntimeException("Transfer failed", e);
} finally {
if (conn != null) try { conn.setAutoCommit(true); conn.close(); } catch (SQLException ignore) {}
}
}
手動獲取連接性能差、易洩漏。引入 HikariCP(Spring Boot 默認):
com.zaxxer HikariCP 5.0.1
// 單例 DataSource
HikariConfig config = new HikariConfig();
config.setJdbcUrl(URL);
config.setUsername(USER);
config.setPassword(PASSWORD);
config.setMaximumPoolSize(20);
config.setMinimumIdle(5);
DataSource ds = new HikariDataSource(config);
// 使用
try (Connection conn = ds.getConnection()) { /* ... */ }
| 問題 | 解決 |
|---|---|
| ClassNotFoundException | 檢查 maven 依賴範圍非 provided、驅動版本匹配 MySQL 版本 |
| Communications link failure | 檢查 host/port、防火牆、MySQL bind-address、driver 類名 |
| Public Key Retrieval is not allowed | URL 加 allowPublicKeyRetrieval=true(8.0+) |
| 時區錯誤 | URL 加 serverTimezone=UTC 或 Asia/Shanghai |
| 中文亂碼 | URL characterEncoding=utf8、表/庫 utf8mb4、連接 SET NAMES utf8mb4 |