jsp:由rs.last()方法不可用,学习ResultSet游标笔记

本文介绍了在使用Java进行数据库操作时遇到的ResultSet游标不支持last()方法的问题及其解决方案。通过调整Statement对象的创建方式,指定游标类型为可滚动类型,解决了获取数据集总行数的需求。

问题起因:
今天学习做一个文章列表翻页的程序,需要获得数据集中的数据总行数
我用的方法如下:
--------------------------------------------------
int RowCount = 0;
rs.last();
RowCount= rs.getRow(); //移动到最后,检索当前行编号,获取总行数 。
out.print("总行数:" + RowCount + "<br/>");
//out.print("isLast:" + rs.isLast() + "<br/>");
//out.print("isAfterLast:" + rs.isAfterLast() + "<br/>");
rs.beforeFirst(); //便于后面输出数据
---------------------------------------------------
执行到rs.last()时候就提示不支持这个方法!
[Microsoft][SQLServer 2000 Driver for JDBC]Unsupported method: ResultSet.last  

资料分析:
=============================游标只读向前================================
java.sql
接口:Connection
方法:
createStatement
Statement createStatement()
               throws SQLException
创建一个 Statement 对象来将 SQL 语句发送到数据库。
没有参数的 SQL 语句通常使用 Statement 对象执行。
如果多次执行相同的 SQL 语句,使用 PreparedStatement 对象可能更有效。
使用返回的 Statement 对象创建的结果集在默认情况下类型为 TYPE_FORWARD_ONLY,
并带有 CONCUR_READ_ONLY 并发级别。[---注意这里,默认是只读向前的游标]

返回:
一个新的默认 Statement 对象
抛出:
SQLException - 如果发生数据库访问错误

===========================游标自定义======================================
java.sql
接口:Connection
方法:createStatement
Statement createStatement(int resultSetType,
                            int resultSetConcurrency)
                            throws SQLException
创建一个 Statement 对象,该对象将生成具有

给定类型和并发性的 ResultSet 对象。此方法与上述 createStatement 方法相同,但它允许重写

默认结果集类型和并发性。

参数:
resultSetType - 结果集类型,它是
---ResultSet.TYPE_FORWARD_ONLY、 //游标向前
---ResultSet.TYPE_SCROLL_INSENSITIVE 或 //该常量指示可滚动但通常不受其他的更改影响的rs类型
---ResultSet.TYPE_SCROLL_SENSITIVE 之一//常量指示可滚动并且通常受其他的更改影响的rs类型。

resultSetConcurrency - 并发类型;它是
---ResultSet.CONCUR_READ_ONLY 或     //只读
---ResultSet.CONCUR_UPDATABLE 之一 //可以修改
返回:
一个新的 Statement 对象,该对象将生成具有给定类型和并发性的 ResultSet 对象
抛出:
SQLException - 如果发生数据库访问错误,或者给定参数不是指示类型和并发性的 ResultSet 常量
从以下版本开始:
1.2

解决办法:

在创建Statement对象时,指定游标参数
conn = DriverManager.getConnection(getConnectionUrl(),dbUserName,dbPassword);
stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);

 
<think>好的,我现在需要帮用户解决Java中遇到的IllegalStateException异常,具体涉及结果集元组没有字段结构的情况。首先,我得理解用户的问题。用户提到的是在使用ResultSet时出现这个异常,并且提到“no field structure”,这可能是指结果集的结构中缺少预期的字段。 首先,我应该回忆一下常见的导致IllegalStateException的原因。比如,在数据库操作中,可能是在关闭了ResultSet之后尝试访问它,或者是在处理结果集时没有正确移动游标。但用户特别提到了“resultset tuples no field structure”,所以可能的问题点在于访问的字段存在于结果集中。 接下来,我需要参考用户提供的引用内容。虽然用户给的引用大部分是关于OkHttp和Stream的Duplicate key问题,但可以忽略这些,因为用户现在的问题是关于ResultSet的。过,可能用户之前的问题可能和这些有关,但根据当前问题,应该集中在数据库操作上。 常见的情况可能是,当使用ResultSet的getXXX方法获取字段时,字段名拼写错误,或者字段存在。比如,尝试用getString("user_name"),但实际查询的结果中没有这个字段,或者字段名是“username”。这时候就会抛出IllegalStateException,提示没有这样的字段结构。 另外,还有一种可能是,在获取结果集的时候,可能已经调用了close()方法,导致结果集被关闭,再次访问时会抛出异常。例如,如果在遍历结果集之后没有正确关闭,或者在遍历过程中提前关闭了连接。 还有一种情况是,当使用某些框架或库时,可能结果集的结构被动态改变,或者元数据没有被正确解析,导致字段结构无法识别。 接下来,我需要思考解决方案。首先,检查SQL查询语句,确保查询的字段在数据库表中存在,并且别名正确。其次,在代码中使用ResultSet方法时,使用正确的字段名或索引。此外,确保在访问结果集之前没有关闭相关的连接或结果集本身。 另外,可能需要检查JDBC驱动是否正确,或者是否有版本兼容的问题,导致元数据解析错误。此外,使用ResultSetMetaData来动态获取字段信息,可以避免硬编码字段名带来的问题。 用户的问题可能出现在类似以下代码中: ResultSet rs = statement.executeQuery("SELECT id, name FROM users"); while(rs.next()) { String email = rs.getString("email"); // 这里如果email字段存在,就会抛出异常 } 这时候,正确的做法是检查查询是否包含email字段,或者在代码中使用正确的字段名。 另外,可能用户在尝试访问结果集的时候,结果集已经关闭,比如在关闭了Connection或Statement之后,再去访问ResultSet,这时候也会抛出IllegalStateException。例如: Connection conn = ...; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(...); conn.close(); // 关闭连接 rs.next(); // 这里会抛出异常,因为连接已关闭,结果集也被关闭了 这种情况下,需要确保在访问结果集的时候,相关的连接和语句仍然是打开的,并且在处理完毕后正确关闭资源,通常使用try-with-resources来管理。 总结可能的解决方案步骤: 1. 检查SQL查询语句中的字段是否存在,是否拼写正确。 2. 使用ResultSetMetaData动态获取字段信息,避免硬编码。 3. 确保在访问结果集时,相关的数据库连接和语句未关闭。 4. 使用正确的字段名或索引访问结果集。 5. 检查JDBC驱动和数据库的兼容性。 然后,我需要验证这些思路是否正确。比如,访问存在的字段是否会抛出IllegalStateException?根据JDBC的文档,当使用getString(String columnLabel)时,如果列名存在,通常会抛出SQLException,如SQLException: Column not found。但可能在某些情况下,比如结果集已经关闭,或者元数据无法获取时,会抛出IllegalStateException。过更常见的是,当结果集已经关闭时,调用其方法会抛出IllegalStateException,例如“Operation not permitted after ResultSet closed”。 所以,用户的问题可能是两种情况: 1. 结果集已经关闭,再次访问。 2. 字段名存在,导致异常。 但根据用户描述中的“no field structure”,可能是指字段结构存在,即访问了存在的字段名。这时候,可能更准确的是SQLException,但可能在某些框架或封装中,会转化为IllegalStateException。或者用户可能混淆了异常类型。 需要进一步考虑,比如在使用Spring的JdbcTemplate时,可能会将底层异常包装成同的异常类型。或者在ORM框架中,如Hibernate,可能会有同的异常处理机制。 过,回到用户的问题,用户明确提到了IllegalStateException,所以可能更可能的情况是结果集已经关闭,或者在访问结果集时处于无效状态,比如没有调用next()方法移动游标。 例如: ResultSet rs = ...; rs.getString("name"); // 没有先调用rs.next(),此时游标在before first位置,直接访问字段会抛出异常 这时候会抛出IllegalStateException,提示结果集当前位置无效。 但根据JDBC规范,这种情况下应该抛出SQLException,比如“ResultSet not positioned properly”之类的。可能同的驱动实现会有同的异常抛出,或者用户的环境中有其他因素导致异常类型同。 因此,用户的问题可能需要具体分析代码中的操作步骤,比如是否正确移动游标,是否关闭了结果集,是否正确处理了字段名。 综合以上分析,可能的解决方案包括: - 确保在访问结果集字段前调用next()方法移动游标到有效行。 - 检查字段名是否正确,使用ResultSetMetaData获取所有列名。 - 确保结果集、语句和连接在使用期间未关闭。 - 使用try-with-resources正确管理资源,避免提前关闭。 现在需要将这些思路整理成结构化的回答,分点说明原因和解决方法,并生成相关问题。</think>### Java.lang.IllegalStateException: ResultSet元组无字段结构解决方案 此异常通常发生在以下场景: 1. **字段名称拼写错误或存在** 尝试通过错误字段名访问结果集,例如: ```java ResultSet rs = statement.executeQuery("SELECT id, name FROM users"); rs.next(); String email = rs.getString("email"); // "email"字段未在查询中定义 ``` 使用`ResultSetMetaData`验证字段是否存在: ```java ResultSetMetaData metaData = rs.getMetaData(); for (int i=1; i<=metaData.getColumnCount(); i++) { System.out.println(metaData.getColumnName(i)); } ``` 2. **操作已关闭的ResultSet** 若提前关闭数据库连接或结果集,再次访问会触发异常: ```java Connection conn = dataSource.getConnection(); ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM table"); conn.close(); // 关闭连接 rs.next(); // 抛出IllegalStateException: Operation not permitted after ResultSet closed ``` 应通过`try-with-resources`管理资源: ```java try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM table")) { // 操作结果集 } ``` 3. **未正确移动结果集游标** 访问字段前未调用`next()`方法定位到有效行: ```java ResultSet rs = stmt.executeQuery("SELECT * FROM table"); String value = rs.getString("column"); // 未调用rs.next()游标在起始位置前 ``` 正确操作应始终先调用`next()`: ```java if (rs.next()) { String value = rs.getString("column"); } ``` ### 其他注意事项 - **框架封装异常** 某些ORM框架(如Hibernate)可能将底层`SQLException`封装为`IllegalStateException`,需结合日志排查具体原因[^3]。 - **动态字段映射问题** 若SQL使用`UNION`或动态生成字段,需确保结果集结构与代码预期一致。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值