Class.forName("com.mysql.cj.jdbc.Driver")DriverManager.getConnection(url, user, pwd) 或 DataSource (JNDI)executeQuery() (SELECT) / executeUpdate() (DML/DDL)
// 創建時指定類型與併發性
Statement stmt = conn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE, // 可滾動,不感知他人修改
ResultSet.CONCUR_UPDATABLE // 可更新
);
ResultSet rs = stmt.executeQuery("SELECT id, name, score FROM students");
// 絕對/相對定位
rs.absolute(5); // 移至第 5 行
rs.relative(-2); // 向前 2 行
rs.first(); rs.last(); rs.beforeFirst(); rs.afterLast();
// 更新當前行
rs.updateInt("score", 100);
rs.updateRow(); // 同步到數據庫
// 插入新行
rs.moveToInsertRow();
rs.updateString("name", "新生");
rs.updateInt("score", 88);
rs.insertRow();
rs.moveToCurrentRow();
注意:MySQL 需主鍵且查詢單表才支持可更新結果集;Oracle/PostgreSQL 支持更豐富。
Statement stmt = conn.createStatement();
stmt.addBatch("INSERT INTO log VALUES (1, 'msg1')");
stmt.addBatch("INSERT INTO log VALUES (2, 'msg2')");
stmt.addBatch("UPDATE stats SET cnt = cnt + 1");
int[] counts = stmt.executeBatch(); // 每條語句影響行數
String sql = "INSERT INTO orders(user_id, amount) VALUES (?, ?)";
PreparedStatement ps = conn.prepareStatement(sql);
for (Order o : orders) {
ps.setLong(1, o.getUserId());
ps.setBigDecimal(2, o.getAmount());
ps.addBatch();
}
int[] results = ps.executeBatch(); // 單次網絡往返執行所有
性能提升數量級,必須配合 rewriteBatchedStatements=true (MySQL) 或類似驅動參數。
conn.setAutoCommit(false); // 關閉自動提交
try {
// 業務邏輯:多條 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); // 恢復默認
}
關鍵點:同一事務內多條 SQL 必須共用同一 Connection;每條執行前關閉上一個 Statement 避免游標衝突。
PreparedStatement 減少解析開銷SQLTransientException 可重試,SQLNonTransientException 需人工干預Blob/Clob 使用流式讀寫,避免一次性載入內存