【问题标题】:ResultSet: Exception: set type is TYPE_FORWARD_ONLY -- why?结果集:异常:集类型为 TYPE_FORWARD_ONLY - 为什么?
【发布时间】:2011-06-16 06:03:05
【问题描述】:

我有非常简单的代码:

pstat=con.prepareStatement("select typeid from users where username=? and password=?");             
pstat.setString(1, username);
pstat.setString(2, password);
rs=pstat.executeQuery();
int rowCount=0;
while(rs.next())
{       
    rowCount++;         
}
rs.beforeFirst();
if(rowCount>=1)
{
while(rs.next())
{
    typeID=rs.getInt(1);
}

但是当执行这段代码时,我得到...

java.sql.SQLException: Result set type is TYPE_FORWARD_ONLY
at sun.jdbc.odbc.JdbcOdbcResultSet.beforeFirst(Unknown Source)
at server.ClientImpl.login(ClientImpl.java:57)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

这是什么原因造成的,我该如何解决?

【问题讨论】:

  • 这个问题永远不会老!在独立于平台的 J-Connector 8.0.15 上,我从来没有遇到过这个错误!所以试试这个侥幸;-)

标签: java sql resultset jdbc-odbc


【解决方案1】:

将您的第一个语句更改为此

pstat=con.prepareStatement("select typeid from users where username=? and password=?",
                            ResultSet.TYPE_SCROLL_SENSITIVE, 
                        ResultSet.CONCUR_UPDATABLE);

这样你可以前进和后退,所以担心的事情更少

【讨论】:

    【解决方案2】:

    TYPE_FORWARD_ONLY 类型表示您只能在结果集上向前移动,不能向后移动,因此当您尝试返回 beforeFirst() 时会出现异常。相反,您可以使用以下prepareStatement(),它接收结果集类型作为参数,或者这样做:

            pstat=con.prepareStatement("select typeid from users where username=? and password=?");             
            pstat.setString(1, username);
            pstat.setString(2, password);
            rs=pstat.executeQuery();
            int rowCount=0;
    
            while(rs.next())
            {
                rowCount++;
                typeID=rs.getInt(1);
            }
    

    【讨论】:

    • 我正要打字。干得好,@MByD
    【解决方案3】:

    这个问题虽然老了,但答案不老,今天遇到了类似的问题,我就是这样处理的,如here 这是 Java JDBC 驱动程序和 PostgreSQL 数据库提供的功能。 本例使用默认参数创建Statement对象,系统生成的数据集只能单向向前移动指针,不能双向移动数据记录指针,前者

    语句stmt = dbConn.createStatement();
    结果 rs = stmt.executeQuery (sql);

    改为
    语句 stmt = dbConn.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
    结果 rs = stmt.executeQuery (sql);

    此时生成的rs可以使用rs.first()反向移动指针操作

    【讨论】:

      【解决方案4】:

      您只能对类型为 TYPE_SCROLL_SENSITIVE 的结果集执行此操作,该类型被定义为“指示可滚动且通常对其他人所做的更改敏感的 ResultSet 对象的类型的常量。”

      您需要执行以下操作...

      Statement statement = 
       connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
          ResultSet.CONCUR_READ_ONLY);
      

      【讨论】:

        【解决方案5】:

        java.sql.SQLException:结果集类型为 TYPE_FORWARD_ONLY

        使用 JDBC 2.0 API,用户可以灵活地向前或向后移动光标。

        您的错误可以通过如下创建语句来消除

        Statement st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
        

        另外,计算行数的更好方法是

        rs=pstat.executeQuery();                //execute the query
        rs.last();                              //move the cursor to the last row
        int numberOfRows = rs.getRow();         //get the number of rows
        rs.beforeFirst();                       //back to initial state
        

        【讨论】:

          【解决方案6】:

          就像例外所说的那样:除了向前之外,您不能在任何其他方向滚动结果集。因此,当您遍历结果集以获取行数时(我什至不明白您为什么这样做),那么这一行将引发该异常:

          rs.beforeFirst();
          

          因为那会向后滚动。

          创建您的语句以便您可以滚动它(例如 Google)或删除该行计数。我建议后者,因为计数似乎没有必要。

          【讨论】:

            【解决方案7】:

            这个问题很老了。我相信已经找到了解决方案。但是,我想在这里提出一些与 Aditya 不同的建议。

            pstat=con.prepareStatement("select typeid from users where username=? and password=?",
                                            ResultSet.TYPE_SCROLL_INSENSITIVE, 
                                        ResultSet.CONCUR_UPDATABLE);
            

            我会使用 INSENSITIVE,而不是 ResultSet.TYPE_SCROLL_SENSITIVE

            Check this link for refernce

            【讨论】:

              【解决方案8】:

              rowCount 变量不是必需的。您正在 rs 上执行两个循环。只需要第二个循环来获取这部分代码完成的行数:

               while (rs.next()){
               typeID=rs.getInt(1); //typeID is the number of rows in the ResultSet
              }
              

              【讨论】:

                【解决方案9】:

                Java 8 documentation 声明如下:

                默认的 ResultSet 对象是不可更新的,并且有一个只能向前移动的光标。因此,您只能遍历它一次,并且只能从第一行到最后一行。可以生成可滚动和/或可更新的 ResultSet 对象。下面的代码片段,其中 con 是一个有效的 Connection 对象,说明了如何创建一个可滚动的、对其他人的更新不敏感且可更新的结果集。有关其他选项,请参阅 ResultSet 字段。

                   Statement stmt = con.createStatement(
                                                  ResultSet.TYPE_SCROLL_INSENSITIVE,
                                                  ResultSet.CONCUR_UPDATABLE);
                   ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");
                   // rs will be scrollable, will not show changes made by others,
                   // and will be updatable
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-03-09
                  相关资源
                  最近更新 更多