Connection)Statement/PreparedStatement/CallableStatement)ResultSet/更新計數)close() 逆序關閉)String url = "jdbc:oracle:thin:@127.0.0.1:1521:ORCL";
String user = "system", pwd = "manager";
Class.forName("oracle.jdbc.driver.OracleDriver"); // JDK 6+ 可省略
Connection conn = DriverManager.getConnection(url, user, pwd);
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/myDB");
Connection conn = ds.getConnection(); // 從連接池獲取
生產環境強制使用連接池(HikariCP、Druid、DBCP2),禁止直接 DriverManager。
| 介面 | 適用場景 | 關鍵方法 |
|---|---|---|
Statement | 靜態 SQL、無參數 | executeQuery()/executeUpdate() |
PreparedStatement | 參數化 SQL、防注入、預編譯複用 | setXxx()、executeQuery/Update() |
CallableStatement | 存儲過程/函數 | registerOutParameter()、execute() |
String sql = "INSERT INTO users(id, name, email) VALUES (?, ?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setLong(1, 1001L);
ps.setString(2, "張三");
ps.setString(3, "zhangsan@example.com");
int rows = ps.executeUpdate();
}
ResultSet,游標初始在第一行之前,next() 逐行推進int 影響行數while (rs.next()) {
long id = rs.getLong("id"); // 或 getLong(1)
String name = rs.getString("name");
Date created = rs.getTimestamp("created_at");
}
// 可滾動/可更新 ResultSet
Statement stmt = conn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE, // 可前後移動
ResultSet.CONCUR_UPDATABLE // 可更新
);
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
rs.absolute(5); // 直接跳第 5 行
rs.updateString("name", "新名");
rs.updateRow(); // 寫回數據庫
try (Connection conn = ds.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
while (rs.next()) { /* ... */ }
} // 自動按逆序關閉 rs → ps → conn
舊代碼手動關閉順序:ResultSet → Statement → Connection,每個 close() 獨立 try-catch。
try (Statement stmt = conn.createStatement()) {
stmt.addBatch("INSERT INTO log VALUES (1, 'A')");
stmt.addBatch("UPDATE users SET cnt=cnt+1 WHERE id=1");
stmt.addBatch("DELETE FROM temp WHERE id<100");
int[] counts = stmt.executeBatch(); // 每條 SQL 影響行數
}
String sql = "INSERT INTO batch_demo(id, val) VALUES (?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
for (int i = 1; i <= 10000; i++) {
ps.setInt(1, i);
ps.setString(2, "val_" + i);
ps.addBatch();
if (i % 1000 == 0) ps.executeBatch(); // 分批提交防 OOM
}
ps.executeBatch(); // 剩餘
}
Connection conn = ds.getConnection();
try {
conn.setAutoCommit(false); // 關閉自動提交
// 業務邏輯:多條 SQL 組成原子操作
try (PreparedStatement ps1 = conn.prepareStatement(sql1);
PreparedStatement ps2 = conn.prepareStatement(sql2)) {
ps1.executeUpdate();
ps2.executeUpdate();
}
conn.commit(); // 全部成功提交
} catch (SQLException e) {
conn.rollback(); // 任一失敗回滾
throw e;
} finally {
conn.setAutoCommit(true); // 恢復默認
conn.close();
}
setFetchSize()、ResultSet.TYPE_FORWARD_ONLYConnection| 數據庫 | 驅動類 | URL 範例 |
|---|---|---|
| MySQL 8+ | com.mysql.cj.jdbc.Driver | jdbc:mysql://host:3306/db?useSSL=false&serverTimezone=UTC |
| PostgreSQL | org.postgresql.Driver | jdbc:postgresql://host:5432/db |
| Oracle 19c | oracle.jdbc.OracleDriver | jdbc:oracle:thin:@//host:1521/service_name |
| SQL Server | com.microsoft.sqlserver.jdbc.SQLServerDriver | jdbc:sqlserver://host:1433;databaseName=db;encrypt=true |
| H2 (嵌入式) | org.h2.Driver | jdbc:h2:~/test;AUTO_SERVER=TRUE |
JDBC 是 Java 數據訪問的基石,掌握其核心模式與最佳實踐,是從「會用」走向「用好」的關鍵。