EJB 遠端介面回傳查詢結果集時,ResultSet 無法直接序列化傳輸。常見兩種方案:
ResultSet 複製到記憶體集合public Enumeration ejbFindBigAccounts(double balance) {
Connection con = null;
PreparedStatement ps = null;
try {
con = getConnection();
ps = con.prepareStatement("SELECT id FROM accounts WHERE bal > ?");
ps.setDouble(1, balance);
ResultSet rs = ps.executeQuery();
Vector v = new Vector();
while (rs.next()) {
v.addElement(rs.getString(1));
}
return v.elements(); // 回傳 Enumeration
} catch (SQLException e) {
throw new EJBException(e);
} finally {
close(con, ps);
}
}
缺點:
javax.sql.RowSet 介面繼承 ResultSet,支援離線操作、可序列化、JavaBean 屬性。Sun 參考實作提供三種:
CachedRowSet:通用離線結果集,**最常用**JdbcRowSet:ResultSet 的 JavaBean 封裝 (需連線)WebRowSet:支援 XML 序列化https://developer.java.sun.com/developer/earlyAccess/crs/rowset.jarimport sun.jdbc.rowset.*;public CachedRowSet ejbFindBigAccounts(double balance) {
Connection con = null;
PreparedStatement ps = null;
try {
con = getConnection();
ps = con.prepareStatement("SELECT * FROM accounts WHERE bal > ?");
ps.setDouble(1, balance);
ResultSet rs = ps.executeQuery();
CachedRowSet crs = new CachedRowSetImpl(); // Sun 實作類
crs.populate(rs); // 一鍵複製 ResultSet 內容與中繼資料
return crs; // 直接回傳,自動序列化傳輸
} catch (SQLException e) {
throw new EJBException(e);
} finally {
close(con, ps);
}
}
CachedRowSet crs = remote.ejbFindBigAccounts(10000);
crs.beforeFirst();
while (crs.next()) {
System.out.println("ID: " + crs.getString("id")
+ ", Balance: " + crs.getDouble("bal"));
}
// 甚至支援離線修改後同步回寫 (acceptChanges)
crs.setDouble("bal", newBal);
crs.updateRow();
crs.acceptChanges(conn); // 重新連線同步
| 維度 | Vector | CachedRowSet |
|---|---|---|
| 程式碼量 | 多 (手動迴圈複製) | 少 (populate 一行) |
| 中繼資料保留 | 無 | 完整保留 |
| 游標操作 | 無 | 完整支援 (next/previous/absolute) |
| 離線修改同步 | 不支援 | 支援 (acceptChanges) |
| XML 序列化 | 需自行實作 | WebRowSet 原生支援 |
| 記憶體效率 | 較低 (Object 封裝開銷) | 較高 (資料結構優化) |
| 相依性 | 零 (JDK 核心) | 需額外 rowset.jar |
rowset.jar 部署成本極低,效益極大CachedRowSet 實現了 ADO.NET DataSet 風格的離線資料操作,是 EJB 時代傳輸表格資料的黃金標準。