Java使用Ucanaccess获取数据库列值时遇UcanaccessSQLException求助
问题根源
你遇到的错误核心原因是:ResultSet是单向、一次性的游标对象。当DbUtils.resultSetToTableModel方法执行时,会完整遍历整个ResultSet来构建表格模型,遍历结束后,游标会停在结果集的最后一行之后(无效位置)。此时再尝试调用resultSetToNestedList、手动遍历ResultSet,或者直接调用getInt/getString,都会因为游标不在有效行上触发invalid cursor state错误。
解决方案
有两种可行的解决思路,核心都是保留ResultSet的数据状态,避免游标耗尽后无法读取:
方案1:使用可滚动的ResultSet
在创建Statement时,指定ResultSet为可滚动、只读类型,这样遍历完成后可以将游标移回结果集开头,重新读取数据。
代码示例:
// 连接数据库后,创建可滚动的Statement Statement stmt = conn.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY ); ResultSet rs = stmt.executeQuery("SELECT * FROM tblGeneral"); // 第一步:生成表格模型并渲染到JTable TableModel tableModel = DbUtils.resultSetToTableModel(rs); tblDatabase.setModel(tableModel); // 关键操作:将游标移回结果集的起始位置 rs.beforeFirst(); // 第二步:现在可以正常遍历ResultSet或转换为嵌套列表 List<List<Object>> dataList = DbUtils.resultSetToNestedList(rs); // 手动遍历字段示例(需再次将游标移到开头) rs.beforeFirst(); while (rs.next()) { int targetInt = rs.getInt("你的字段名"); String targetStr = rs.getString("你的字段名"); // 处理获取到的字段值 } // 最后关闭资源释放连接 DbUtils.close(rs); DbUtils.close(stmt);
方案2:使用CachedRowSet缓存结果集
将原始ResultSet的数据缓存到CachedRowSet中,它是一个离线的结果集,不受原始游标位置的影响,且可以重复读取,还能提前释放数据库连接资源。
代码示例:
ResultSet rs = stmt.executeQuery("SELECT * FROM tblGeneral"); // 将ResultSet数据缓存到CachedRowSet CachedRowSet crs = new CachedRowSetImpl(); crs.populate(rs); // 先关闭原始ResultSet和Statement,释放数据库连接 DbUtils.close(rs); DbUtils.close(stmt); // 用缓存的CachedRowSet生成表格模型 TableModel tableModel = DbUtils.resultSetToTableModel(crs); tblDatabase.setModel(tableModel); // 将CachedRowSet游标移回开头,转换为嵌套列表 crs.beforeFirst(); List<List<Object>> dataList = DbUtils.resultSetToNestedList(crs); // 手动遍历CachedRowSet读取字段 crs.beforeFirst(); while (crs.next()) { int targetInt = crs.getInt("你的字段名"); String targetStr = crs.getString("你的字段名"); // 处理获取到的字段值 }
关键注意点
- 无论用哪种方案,重复读取结果集前必须调用
beforeFirst()将游标移回起始位置。 CachedRowSet方案更推荐,因为它可以离线使用,不需要长期占用数据库连接资源,适合需要多次复用结果集的场景。
内容的提问来源于stack exchange,提问作者RedKite
相关产品推荐
相关产品推荐

