CachedRowSet 是 JDBC 中实现离线数据操作的核心实现,通过内存缓存、断连查询、本地修改和显式回写(acceptChanges)完成全流程;需设置主键、启用可写、避免 SELECT *,并注意内存与并发风险。

Java JDBC 中用 RowSet 离线处理数据集,核心是把数据“搬进内存、断开连接、本地操作、按需回写”,既释放数据库连接资源,又提升客户端或中间层的数据操作自由度。关键不在接口本身,而在于选用支持离线能力的具体实现——CachedRowSet 是最常用、JDK 自带、无需额外依赖的选择。
用 CachedRowSet 实现真正断连读取
它不是简单包装 ResultSet,而是把整张结果集复制到内存后主动关闭 Connection 和 ResultSet,彻底脱离数据库。
- 推荐方式:用
RowSetProvider.newFactory().createCachedRowSet()创建实例(JDBC 4.1+ 标准做法) - 设置连接参数:
setUrl()、setUsername()、setPassword();再用setCommand("SELECT ...")指定查询语句 - 调用
execute()—— 此时才建连、查数据、缓存、关连一气呵成,之后无论网络是否中断、Connection 是否关闭,都能正常遍历和取值 - 避免 SELECT *:确保查询包含主键列,否则后续更新/删除可能失败
在内存中自由修改数据
所有增删改都只作用于本地缓存,不触碰数据库,适合表单编辑、批量校验、离线填报等场景。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 定位行:
absolute(3)或beforeFirst()+next() - 更新字段:
updateString("name", "李四")→ 必须跟updateRow()才生效(仅缓存) - 插入新行:
moveToInsertRow()→updateXXX()→insertRow() - 删除行:
deleteRow()(逻辑删除,仍保留在缓存中,直到 acceptChanges) - 注意:
setReadOnly(false)必须提前调用,否则修改操作会抛异常
安全可控地同步回数据库
回写不是自动的,必须显式触发,且依赖主键识别变更意图,避免误更新或丢失数据。
立即学习“Java免费学习笔记(深入)”;
- 调用
acceptChanges():它会重新用之前设置的连接参数建连,自动生成 INSERT/UPDATE/DELETE 语句执行 - 无主键表要手动指定:
setKeyColumns(new int[]{1, 2})(对应主键列在 SELECT 中的位置) - 失败会抛
SQLException,建议捕获并检查getSQLState()或错误码,区分是约束冲突、连接超时还是权限问题 - 成功后状态重置,缓存与数据库一致;若需再次修改,继续操作后再次调用 acceptChanges
避开常见坑,保障稳定性
CachedRowSet 虽方便,但几个隐性约束不注意就容易静默失败或行为异常。
- 内存占用:全量加载,大数据集慎用;可配合
setPageSize()分页加载 - 并发风险:它本身不提供行锁或乐观版本控制(默认用 RIOptimisticProvider,但需数据库配合),高并发修改建议加应用层校验或使用数据库级乐观锁字段
- 序列化传输:因可序列化,适合传给 PDA、移动端或微服务间传递数据,但注意敏感字段脱敏
- 避免旧实现:
com.sun.rowset.CachedRowSetImpl已被标记为受限 API,应优先用 RowSetProvider 创建


















