java.sql.Statement 或 java.sql.PreparedStatement - 带参数的可滚动结果集

java.sql.Statement or java.sql.PreparedStatement - scrollable resultset with parameters

在我的 java 应用程序中,它似乎在我对数据库的查询中使用了参数,我需要利用 PreparedStatement。 但是与此同时,我想在 forward/backward 模式(可滚动)中使用语句的结果集 PreparedStatement 似乎不提供设置滚动模式 语句好像没有提供参数。

似乎是一个基本问题..但我没有想到什么(除了使用 Statement 和构建不带参数的 SQL 之外)。是否真的没有办法向语句提供参数......或者有一个可滚动的准备语句?我错过了什么吗?

            conn = Utility.getConnection();

            tmpSQL = "SELECT * FROM " + baseTable + " WHERE " + filterCriteria
                    + " ORDER BY " + sortCriteria;

//method 1

Statement stmt = conn.createStatement(
                       ResultSet.TYPE_SCROLL_INSENSITIVE,
                       ResultSet.CONCUR_UPDATABLE);

rset = stmt.executeQuery(tmpSQL);  //not using any parameters!


//method 2

            PreparedStatement pStatement = conn.prepareStatement(tmpSQL);  //not scrollable!

            if (params != null)
                for (int i = 0; i < params.size(); i++) {

                    pStatement.setString(i + 1,
                            ((Parameter) params.get(i)).getStringValue());

                }

            rset = pStatement.executeQuery();

使用

PreparedStatement pStatement = conn.prepareStatement(tmpSQL,
                                        ResultSet.TYPE_SCROLL_INSENSITIVE,
                                        ResultSet.CONCUR_UPDATABLE);

Java Doc Info

然后要获取结果集中的记录数,请使用rset.last(),然后使用rset.getRow()。然后使用rset.beforeFirst()将光标放回原来的位置。

一些初始背景评论

可滚动性主要取决于底层数据库。尽管 JDBC 有一个回滚的方法,但它没有实现,例如在 Oracle JDBC 驱动程序中。

我建议避免滚动结果集。事实上,即使它适用于某些数据库,实施起来效率也很低。在 GUI 上使用效率也很低,因为每次滚动都会触发数据库操作,这很慢。

通常的方法是将所有行加载到一个容器(例如 List<...> )并处理它,如果您有中等数量的行(比如最多 1000 行)。如果你有更多的行,那么:

  • 如果你真的需要阅读那么多行,请考虑一下。例如,如果这是一个 GUI 列表,加载 100 万行可能没有意义,因为人类用户不会逐一滚动浏览所有 100 万行。可能更好的过滤 and/or 分页是有意义的。
  • 如果业务端处理确实需要所有的行,那就考虑一下。将所有行从数据库拉到应用程序进行处理是一种效率极低的编程模式。使用存储过程或程序包 (Oracle) 在数据库端处理您的数据。
  • 但如果您真的需要将 1 百万行拉到应用程序进行处理,请以流方式进行处理。 IE。而不是首先将 100 万行提取到内存然后处理它,而是提取一行,处理它,提取另一行,处理它。这也解释了为什么通常不支持向后滚动:这需要驱动程序或数据库在内存中实际保存一百万行 select 的结果,因为你 可能 想要向后滚动。

解决你的问题

要获取记录数,请使用 select count(*) 执行单独的语句。 然后执行另一个 select 实际读取记录并获取它们(仅转发)。

这比读取所有记录只是为了计算它们要快得多。