首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

CachedRowSet 實戰:解決 ResultSet 脫離 Connection 無法跨平台使用的終極方案

     編輯:Java 相關知識

問題背景

JDBC ResultSet 預設為**連線導向**,游標依賴底層 Connection 保持開啟。Windows 下某些驅動允許關閉連線後繼續讀取已緩衝資料,但 **Linux/Unix 驅動嚴格遵循規範,連線關閉即失效**。若直接在 JSP/Service 層傳遞 ResultSet,跨平台部署極易出錯。

CachedRowSet 核心優勢

  • 離線操作:populate(ResultSet) 將資料完整複製至記憶體,斷開連線後仍可序列化、傳遞、修改。
  • 繼承 ResultSet:介面相容,上層程式碼**零修改**即可遷移。
  • 可序列化:支援 RMI、HttpSession 跨 JVM 傳輸。
  • 樂觀鎖更新:acceptChanges() 重新連線寫回,自動偵測衝突。

完整 DAO 遷移範例

public class DBManager {
    private String url, username, password;

    // 原版:回傳 ResultSet (跨平台不穩)
    // public ResultSet getResultSet(String sql) throws Exception { ... }

    // 升級版:回傳 CachedRowSet (實作 ResultSet 介面)
    public ResultSet getResultSet(String sql) throws Exception {
        Connection conn = getConnection(); // 從連線池取得
        try {
            CachedRowSet crs = new CachedRowSetImpl(); // com.sun.rowset.CachedRowSetImpl (JDK 內建) 或 javax.sql.rowset.CachedRowSet (JDBC 4.0+)
            crs.setUrl(url);
            crs.setUsername(username);
            crs.setPassword(password);
            crs.setCommand(sql);
            crs.execute(conn); // 內部自動 populate 並關閉連線
            return crs; // 直接回傳,型別相容
        } catch (Exception e) {
            throw new Exception("獲取 CachedRowSet 失敗: " + e.getMessage() + "\nSQL: " + sql);
        } finally {
            freeConnection(conn); // 確保連線歸還池中
        }
    }
}

關鍵使用細節

操作說明
crs.execute(conn)執行查詢、填充資料、自動關閉傳入連線 (若為 pooled connection 需確認行為)
crs.beforeFirst()游標重置至起始位置 (預設已在 beforeFirst)
crs.next()逐筆讀取,與 ResultSet 完全一致
crs.updateString("col", "val")修改當前行資料 (需 crs.acceptChanges() 寫回)
crs.acceptChanges()重新取得連線寫回資料庫,樂觀鎖失敗拋 SyncProviderException
crs.release()釋放資源 (JDK 實作建議顯式呼叫)

依賴與相容性

  • JDK 1.5+:com.sun.rowset.CachedRowSetImpl (Sun 內建實作,非標準 API)。
  • JDBC 4.0 (Java 6+):javax.sql.rowset.CachedRowSet 標準介面,配合 RowSetProvider.newFactory().createCachedRowSet() 取得實作。
  • 第三方實作:Apache Commons DbUtils RowSetFactory、Spring CachedRowSetFactoryBean。

效能與記憶體考量

  • 全量載入記憶體:結果集極大 (百萬列) 時易 OOM,應改用分頁查詢 (LIMIT/OFFSET 或游標)。
  • 網路傳輸:序列化傳輸時體積 = 資料量 + 中繼資料,大結果集建議壓縮或改用串流式 API。
  • 並發修改:acceptChanges() 預設比較所有欄位偵測衝突,大表可自訂 SyncProvider 僅比較版本欄位/時間戳。

遷移檢查清單

  1. DAO 回傳型別改為 javax.sql.RowSet 或 ResultSet (介面)。
  2. 確認所有呼叫端僅使用 ResultSet 介面方法 (無驅動專屬擴充)。
  3. 單元測試驗證:關閉連線後仍能正常遍歷、序列化/反序列化。
  4. 生產環境監控:記憶體佔用、序列化耗時、樂觀鎖衝突率。

結語

CachedRowSet 以**零修改上層代碼**解決 ResultSet 跨平台離線難題,是舊系統 JDBC 層升級的最高性價比方案。新專案建議直接採用 Spring JdbcTemplate / MyBatis 等高層抽象,從架構層面避免裸露 ResultSet。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved