使用`ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE`創建可更新結果集,卻在`updateXxx`時報`ResultSet is read only`,通常由SQL查詢不滿足可更新條件或數據庫驅動不支持導致。本文系統排查原因並給出解決方案。
| SQL示例 | 原因 |
|---|---|
| `SELECT * FROM t1 JOIN t2 ON ...` | 多表關聯 |
| `SELECT id, COUNT(*) FROM t GROUP BY id` | 聚合查詢 |
| `SELECT id, 'constant' AS flag FROM t` | 常量列 |
| `SELECT id, UPPER(name) AS uname FROM t` | 表達式列 |
| `SELECT * FROM view_name` | 視圖可能不可更新 |
| `SELECT id, name FROM t WHERE id IN (SELECT ...)` | 子查詢(部分驅動不支持) |
// 嘗試敏感游標
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
// 或 僅前向只讀但可更新(部分驅動支持)
Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
**不要在業務代碼中使用可更新ResultSet**,理由:
標準做法:查詢獲取數據 → 內存中修改對象 → 執行參數化`UPDATE`語句:
String sql = "UPDATE my_table SET column = ? WHERE pk = ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, newValue);
ps.setInt(2, id);
ps.executeUpdate();
}
現代數據訪問原則:查詢用ResultSet/ORM,更新用PreparedStatement/JPA/Hibernate/MyBatis,職責分離才專業。