简体   繁体   English

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

[英]java.sql.Statement or java.sql.PreparedStatement - scrollable resultset with parameters

In my java app, it seems to use parameters in my query to the database, I need to utilize the PreparedStatement. 在我的java应用程序中,它似乎在我的查询中使用参数到数据库,我需要利用PreparedStatement。 However at the same time, I would like to use the resultset from the statement in forward/backward mode (scrollable) PreparedStatement does not seem to offer setting the scrollable mode Statement does not seem to offer parameters. 但是同时,我想在前进/后退模式(可滚动)中使用语句的结果集,PreparedStatement似乎没有提供设置可滚动模式,Statement似乎没有提供参数。

Seems like a basic question..but nothing jumping out at me (other than using Statement and constructing the SQL without parameters). 看起来像一个基本问题..但没有什么东西跳出来(除了使用Statement和构造没有参数的SQL)。 Is there really no way to supply parameters to a Statement..or have a preparedstatement scrollable? 真的没有办法为Statement提供参数。或者有一个可滚动的预备语句吗? Am I missing something? 我错过了什么吗?

            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();

Use 使用

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

Java Doc Info Java Doc Info

Then to get the count of records in your ResultSet, use rset.last() followed by rset.getRow() . 然后,要获取 ResultSet中的记录计数 ,请使用rset.last()然后使用rset.last() rset.getRow() Then use rset.beforeFirst() to put the cursor back to where it was initially. 然后使用rset.beforeFirst()将光标放回原来的位置。

Some initial background comments 一些初步的背景评论

Scrollability is mostly depending on the underlying database. 可滚动性主要取决于底层数据库。 Even though JDBC has a method to scroll back, it is not implemented eg in Oracle JDBC driver. 尽管JDBC有一种向后滚动的方法,但它并没有在Oracle JDBC驱动程序中实现。

I would suggest to avoid of scrolling the result set. 我建议避免滚动结果集。 In fact even if it works for some databases, it is quite inefficient to implement. 实际上,即使它适用于某些数据库,实现效率也很低。 Also inefficient to use on the GUI, since each scrolling would then trigger a database operation, which is slow. 在GUI上使用效率也很低,因为每次滚动都会触发数据库操作,这很慢。

The usual approach is to load all rows to a container (eg List<...> ) and process that, if you have a moderate number of rows (say up to 1000 rows). 通常的方法是将所有行加载到容器(例如List <...>)并处理该行,如果您有适度的行数(例如最多1000行)。 If you have a lot more rows, then: 如果你有更多的行,那么:

  • think it over if you really need to read that many rows. 如果你真的需要阅读那么多行, 请考虑一下。 For example, if this is a GUI list, it may not make sense loading 1 million rows, since the human user will not one-by-one scroll trough all 1 million rows. 例如,如果这是一个GUI列表,加载100万行可能没有意义,因为人类用户不会逐行滚动所有100万行。 Probably a better filtering and/or pagination would make sense. 可能更好的过滤和/或分页是有意义的。
  • if you really need all the rows for business side processing, then think it over. 如果您真的需要所有行进行业务端处理,那么请仔细考虑一下。 Pulling all rows from the database to the app for processing is a super-inefficient programming pattern. 将所有行从数据库拉到应用程序进行处理是一种超低效的编程模式。 Use stored procedures, or packages (Oracle) to process your data on the database side. 使用存储过程或包(Oracle)来处理数据库端的数据。
  • but if you really really need to pull like 1 millon rows to the app for processing, do the processing in a streaming-manner. 但如果您确实需要将1亿行拉到应用程序进行处理,请以流式方式进行处理。 Ie instead of first fetching 1 million rows to the memory and then processing it, fetch one row, process it, fetch another row, process it. 也就是说,而不是首先向内存中提取100万行然后处理它,获取一行,处理它,获取另一行,处理它。 This also explains why back-scrolling is usually not supported: that would require the driver or the db to actually hold in memory one million rows of the result of your select, because you might want to scroll back. 这也解释了为什么通常不支持反向滚动:这需要驱动程序或数据库实际在内存中保存一百万行的结果,因为您可能想要向后滚动。

To solve your question 解决你的问题

To get the count of records, execute a separate statement with select count(*). 要获取记录计数,请使用select count(*)执行单独的语句。 Then execute another select to actually read the records and fetch them (only forward). 然后执行另一个选择以实际读取记录并获取它们(仅向前)。

It is much faster than reading all records just to count them. 它比读取所有记录要快得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法在Java中准备Postgres语句(java.sql.PreparedStatement) - Unable to Prepare a Postgres Statement in Java (java.sql.PreparedStatement) java.sql.PreparedStatement 的 setBoolean() 方法 - setBoolean() method of java.sql.PreparedStatement Janino 找不到 java.sql.PreparedStatement 如果 mvn 测试 - Janino cant find java.sql.PreparedStatement if mvn test jdbc java.sql.preparedstatement在插入期间复制行 - jdbc java.sql.preparedstatement duplicating rows during insert 类型不匹配:无法从java.sql.PreparedStatement转换为jdbcDemo.PreparedStatement - Type mismatch: cannot convert from java.sql.PreparedStatement to jdbcDemo.PreparedStatement java.sql.PreparedStatement 无法转换为 com.mysql.jdbc.PreparedStatement - java.sql.PreparedStatement cannot be converted to com.mysql.jdbc.PreparedStatement com.mysql.jdbc.PreparedStatement包之间的区别是什么? 和java.sql.PreparedStatement? - What is the difference between package com.mysql.jdbc.PreparedStatement; and java.sql.PreparedStatement? 使用java.sql.Statement执行多行sybase语句 - Execute Multiline sybase statement with java.sql.Statement 为什么java.sql.Statement是接口而不是抽象类? - Why is java.sql.Statement an interface and not an abstract class? 在单个java.sql.Statement上执行多个DML - Execute Multiple DML on single java.sql.Statement
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM