Java
Z
信頼度ランク
| S | 公式ソース確認済み |
| A | 成功実績多数・失敗例少数 |
| B | 賛否両論 |
| C | 動作未確認・セキュリティリスク高 |
| Z | 個人所感 |
JavaのJDBC接続トラブルシューティング完全ガイド
JDBC接続の基本から、ClassNotFoundException/SQLException/タイムアウトなどよくあるエラーの原因と解決方法、コネクションプールの正しい使い方まで解説します。
一言結論
JDBCトラブルの大半はドライバJARの欠如・URL誤記・コネクションリークの3つに集約され、try-with-resourcesでConnectionを必ず閉じることがコネクションプール枯渇を防ぐ最重要対策だ。
JDBC 接続の基本
String url = "jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=Asia/Tokyo";
String user = "root";
String password = "password";
try (Connection conn = DriverManager.getConnection(url, user, password)) {
System.out.println("接続成功");
} catch (SQLException e) {
System.err.println("接続失敗: " + e.getMessage());
}
よくあるエラーと解決方法
1. ClassNotFoundException
java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver
原因: JDBCドライバのJARがクラスパスにない。
解決(Maven):
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.1.0</version>
</dependency>
他のデータベース:
<!-- PostgreSQL -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.6.0</version>
</dependency>
<!-- H2(インメモリDB、開発・テスト用) -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.2.224</version>
<scope>test</scope>
</dependency>
2. Communications link failure
com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure
原因と対処:
| 原因 | 対処 |
|---|---|
| MySQL サーバーが起動していない | サービスを起動する |
| ポート番号が違う | `netstat -an |
| ファイアウォールがブロック | ポートを開放する |
| ホスト名が間違っている | URL を確認 |
| SSL が必要 | useSSL=true または requireSSL=true |
3. Access denied
java.sql.SQLException: Access denied for user 'root'@'localhost'
解決:
-- MySQLで権限を確認
SHOW GRANTS FOR 'root'@'localhost';
-- 権限を付与
GRANT ALL PRIVILEGES ON mydb.* TO 'root'@'localhost';
FLUSH PRIVILEGES;
4. Too many connections
com.mysql.cj.jdbc.exceptions.CommunicationsException: ... Too many connections
原因: 接続を閉じずにリークしている。
確認:
SHOW STATUS LIKE 'Threads_connected';
SHOW PROCESSLIST;
解決: 接続を確実に閉じる(try-with-resources):
// NG: 接続を閉じていない
Connection conn = DriverManager.getConnection(url, user, pass);
Statement stmt = conn.createStatement();
stmt.executeQuery(sql);
// → conn が閉じられない
// OK: try-with-resources
try (Connection conn = DriverManager.getConnection(url, user, pass);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
System.out.println(rs.getString("name"));
}
}
5. タイムアウト
com.mysql.cj.exceptions.CJCommunicationsException: The last packet sent successfully...
長時間未使用の接続が切れている問題です。
解決(接続URLにタイムアウト設定):
jdbc:mysql://localhost:3306/mydb?connectTimeout=5000&socketTimeout=30000
コネクションプールを使う場合(HikariCP):
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("root");
config.setPassword("password");
config.setMaximumPoolSize(10);
config.setConnectionTimeout(30000);
config.setIdleTimeout(600000);
config.setMaxLifetime(1800000);
config.setKeepaliveTime(300000); // 5分ごとにkeepalive
HikariDataSource ds = new HikariDataSource(config);
6. SQLState の読み方
SQLException の getSQLState() で原因が分かります:
| SQLState | 意味 |
|---|---|
08001 | 接続確立失敗 |
08S01 | 通信リンク障害 |
42000 | 構文エラー |
23000 | 一意性制約違反 |
40001 | デッドロック |
} catch (SQLException e) {
System.err.println("SQLState: " + e.getSQLState());
System.err.println("ErrorCode: " + e.getErrorCode());
System.err.println("Message: " + e.getMessage());
}
PreparedStatement でSQLインジェクションを防ぐ
// NG: SQLインジェクション脆弱性
String sql = "SELECT * FROM users WHERE name = '" + name + "'";
// OK: PreparedStatement
String sql = "SELECT * FROM users WHERE name = ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, name);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
System.out.println(rs.getString("email"));
}
}
}
コネクションプール(HikariCP)のモニタリング
// JMX でプールの状態を確認
HikariPoolMXBean poolMXBean = hikariDataSource.getHikariPoolMXBean();
System.out.println("アクティブ接続: " + poolMXBean.getActiveConnections());
System.out.println("アイドル接続: " + poolMXBean.getIdleConnections());
System.out.println("待機スレッド: " + poolMXBean.getThreadsAwaitingConnection());
まとめ
| エラー | まず確認すること |
|---|---|
| ClassNotFoundException | JARがクラスパスにあるか |
| Communications link failure | DBサーバーが起動しているか、URLが正しいか |
| Access denied | ユーザー名/パスワード/権限 |
| Too many connections | 接続リーク(try-with-resources を使っているか) |
| タイムアウト | コネクションプールの keepalive 設定 |
現代の Java アプリでは DriverManager を直接使わず、HikariCP などのコネクションプールを通じて接続するのが標準的です。