【问题标题】:ResultSet loses first valueResultSet 丢失第一个值
【发布时间】:2023-03-27 16:36:01
【问题描述】:

代码似乎工作正常,但我注意到每当我查询一个只有一个结果的字符串时,它什么都没有返回。不知何故,我跳过了我认为的第一个结果,但不知道为什么。

    else{
   Conn con = null;
   try {
    con = new Conn();
   } catch (Exception e) {

    e.printStackTrace();
   }
   String sql = "SELECT productname, quantityperunit, unitprice FROM products pr, categories ca WHERE pr.categoryID = ca.categoryID AND ProductName LIKE '%" + searchTerm + "%'";
   System.out.println("last try");
   try {
    searchResults = con.query(sql);

    if (searchResults.next()){
     session.setAttribute("searchResults", searchResults);
    }


   } catch (Exception e) {

    e.printStackTrace();
   } 


  }

这是显示代码:

 java.sql.ResultSet resultSet = (java.sql.ResultSet) session.getAttribute("searchResults");
    if(resultSet == null){
     out.println("Nullified");
    }
 if(resultSet!=null){
  out.println("<table border='1'>");
     out.println("<tr><th>Product Name</th><th>Quantity per Item</th><th>Price</th><th>Quantity</th><th><Add to Cart</th></tr>");
     while(resultSet.next()){      
      out.println("<tr><td>"+resultSet.getString("ProductName")+"</td></tr>");
     }
     out.println("</table>");
 }

任何帮助将不胜感激。

【问题讨论】:

  • 抱歉格式化,我似乎无法正常工作...
  • 要格式化代码,缩进4个空格。您可以通过选择作品并按下编辑器工具栏中的010101 按钮或Ctrl+K 键来完成。我已经为你做了。
  • Khorkrak 已经确定了。我只想补充一点,这真的不是编码方式。 JDBC 代码正在泄漏资源。模型、视图和控制器逻辑混合在一起。异常处理是虚假的。会话范围被滥用。在如何正确操作之前,我已经发布了几个带有示例的答案,看看:thisthisthis
  • 感谢 BalusC 的帮助,请原谅我的菜鸟,但他是我第一次听说 JSTL。

标签: java jsp servlets jdbc


【解决方案1】:

我认为 resultSet.next() 会将光标移动到下一个结果,因此它会在 while 循环的第一次迭代中立即跳过第一个结果。

【讨论】:

  • 嗯。还有其他方法可以检查我的结果集是否为空?
  • 是的,将其映射到List&lt;RowObject&gt; 并通过List#isEmpty()List#size() 对其进行测试。另请参阅this answer
  • 这个答案不正确。来自docs: "将光标从当前位置向前移动一行。ResultSet 光标最初位于第一行之前;第一次调用 next 方法使第一行成为当前行;第二次调用使第二行成为当前行,依此类推。".
【解决方案2】:

根据API docs for ResultSet next

将光标从当前位置向前移动一行。 ResultSet 游标最初位于第一行之前;第一次调用next 方法使第一行成为当前行;第二次调用使第二行成为当前行,依此类推。

但在您的代码中,在进入while 循环之前,您将光标移动到第一行:

searchResults = con.query(sql);
if (searchResults.next()){
    session.setAttribute("searchResults", searchResults);
}

解决这个问题的一种方法是改变这个:

while(resultSet.next()) {
   out.println(""+resultSet.getString("ProductName")+""); } out.println(""); 
}

到这里:

do {
   out.println(""+resultSet.getString("ProductName")+""); } out.println("");
} while(resultSet.next());

或者,如果您的 JDBC 驱动程序支持,您可以在将结果集放入会话后调用 beforeFirst()

searchResults = con.query(sql);
if (searchResults.next()){
    session.setAttribute("searchResults", searchResults);
    searchResults.beforeFirst();
}

无论如何,当searchResults 被放入会话时,第一行由于对searchResults.next() 的调用而丢失:

searchResults = con.query(sql);
if (searchResults.next()){
    session.setAttribute("searchResults", searchResults);
}

【讨论】:

  • 刚刚对此进行了测试,效果很好,如果我的 JSTL 尝试失败,将退回到它。谢谢你!
【解决方案3】:

对于那些使用 Spring JDBC 并看到此行为的人,请注意 ResultSetExtractor 的代码如下:

/**
 * Adapter to enable use of a RowCallbackHandler inside a ResultSetExtractor.
 * <p>Uses a regular ResultSet, so we have to be careful when using it:
 * We don't use it for navigating since this could lead to unpredictable consequences.
 */
private static class RowCallbackHandlerResultSetExtractor implements ResultSetExtractor<Object> {

    private final RowCallbackHandler rch;

    public RowCallbackHandlerResultSetExtractor(RowCallbackHandler rch) {
        this.rch = rch;
    }

    @Override
    public Object extractData(ResultSet rs) throws SQLException {
        while (rs.next()) {
            this.rch.processRow(rs);
        }
        return null;
    }
}

因此,当您使用接口并提供 lambda 来映射行时,不要犯与我相同的错误,并像这样再次包含 while(resultSet.next()) 循环,否则您还会看到您正在跳过第一个行:

// THIS IS BAD AND WILL MAKE YOU SKIP THE FIRST RESULT
new JdbcTemplate(getDataSource()).query(sql, resultSet -> {
    while(resultSet.next()) {
        myMappingFunction();
    }
});

正确的方法是编写映射行的代码:

new JdbcTemplate(getDataSource()).query(sql, resultSet -> {
    myMappingFunction();
});

【讨论】:

  • 这对我很有帮助。我的 Spring JDBC CallbackHandler 无意中在其中包含了 while 循环(从以前的未使用回调的实现代码 sn-p 遗留下来)。棘手的想法是,对于结果 > 1,事情可能看起来很正常。回调被调用,然后处理整个结果集......同时您可能不知道回调只是被调用一次而不是重复调用,并且您看到的是 2 -> n 结果而不是 1 -> n。
猜你喜欢
  • 2022-12-22
  • 2019-09-27
  • 1970-01-01
  • 2012-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-10
相关资源
最近更新 更多