Как получить количество строк с помощью ResultSet в Java? - PullRequest
64 голосов
/ 25 октября 2011

Я пытаюсь создать простой метод, который получает ResultSet в качестве параметра и возвращает int, который содержит количество строк ResultSet. Это правильный способ сделать это или не так много?

int size = 0;
    try {
        while(rs.next()){
            size++;
        }
    }
    catch(Exception ex) {
        System.out.println("------------------Tablerize.getRowCount-----------------");
        System.out.println("Cannot get resultSet row count: " + ex);
        System.out.println("--------------------------------------------------------");
    }

Я пробовал это:

int size = 0;
try {
    resultSet.last();
    size = resultSet.getRow();
    resultSet.beforeFirst();
}
catch(Exception ex) {
    return 0;
}
return size;

Но я получил сообщение об ошибке com.microsoft.sqlserver.jdbc.SQLServerException: The requested operation is not supported on forward only result sets.

Заранее спасибо за указатели!

Ответы [ 13 ]

56 голосов
/ 25 октября 2011

Если у вас есть доступ к подготовленному утверждению, которое приводит к этому набору результатов, вы можете использовать

connection.prepareStatement(sql, 
  ResultSet.TYPE_SCROLL_INSENSITIVE, 
  ResultSet.CONCUR_READ_ONLY);

. Это подготовит ваше утверждение таким образом, что вы сможете перематывать курсор назад.Это также задокументировано в ResultSet Javadoc

В целом, однако, курсоры пересылки и перемотки могут быть весьма неэффективными для больших наборов результатов.Другой вариант в SQL Server - вычислить общее количество строк непосредственно в вашем операторе SQL:

SELECT my_table.*, count(*) over () total_rows
FROM my_table
WHERE ...
34 голосов
/ 26 июня 2012

Ваш SQL-код, создающий код, может выглядеть как

statement = connection.createStatement();

Для решения проблемы "com.microsoft.sqlserver.jdbc.SQLServerException: запрошенная операция не поддерживается для наборов результатов только для пересылки".

statement = connection.createStatement(
    ResultSet.TYPE_SCROLL_INSENSITIVE, 
    ResultSet.CONCUR_READ_ONLY);

После вышеуказанного изменения вы можете использовать

int size = 0;
try {
    resultSet.last();
    size = resultSet.getRow();
    resultSet.beforeFirst();
}
catch(Exception ex) {
    return 0;
}
return size;

чтобы получить количество строк

21 голосов
/ 29 января 2014
Statement s = cd.createStatement();
ResultSet r = s.executeQuery("SELECT COUNT(*) AS rowcount FROM FieldMaster");
r.next();
int count = r.getInt("rowcount");
r.close();
System.out.println("MyTable has " + count + " row(s).");

Иногда JDBC не поддерживает следующий метод, выдающий ошибку, например, `TYPE_FORWARD_ONLY 'использует это решение

Sqlite не поддерживается в JDBC.

resultSet.last();
size = resultSet.getRow();
resultSet.beforeFirst();

Так что тогда используйте это решение.

спасибо ..

7 голосов
/ 29 января 2014

Вместо этого выполните SELECT COUNT(*) FROM ... запрос.

5 голосов
/ 24 мая 2013

Я только что сделал метод получения.

public int getNumberRows(){
    try{
       statement = connection.creatStatement();
       resultset = statement.executeQuery("your query here");
       if(resultset.last()){
          return resultset.getRow();
       } else {
           return 0; //just cus I like to always do some kinda else statement.
       }
    } catch (Exception e){
       System.out.println("Error getting row count");
       e.printStackTrace();
    }
    return 0;
}
3 голосов
/ 12 января 2014

Если у вас есть таблица с сохранением идентификатора как основного и автоматического приращения, тогда это будет работать

Пример кода для получения общего количества строк http://www.java2s.com/Tutorial/Java/0340__Database/GettheNumberofRowsinaDatabaseTable.htm

Ниже приведен код

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;

public class Main {
  public static void main(String[] args) throws Exception {
    Connection conn = getConnection();
    Statement st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
        ResultSet.CONCUR_UPDATABLE);

    st.executeUpdate("create table survey (id int,name varchar(30));");
    st.executeUpdate("insert into survey (id,name ) values (1,'nameValue')");
    st.executeUpdate("insert into survey (id,name ) values (2,null)");
    st.executeUpdate("insert into survey (id,name ) values (3,'Tom')");
    st = conn.createStatement();
    ResultSet rs = st.executeQuery("SELECT * FROM survey");

    rs = st.executeQuery("SELECT COUNT(*) FROM survey");
    // get the number of rows from the result set
    rs.next();
    int rowCount = rs.getInt(1);
    System.out.println(rowCount);

    rs.close();
    st.close();
    conn.close();

  }

  private static Connection getConnection() throws Exception {
    Class.forName("org.hsqldb.jdbcDriver");
    String url = "jdbc:hsqldb:mem:data/tutorial";

    return DriverManager.getConnection(url, "sa", "");
  }
}
2 голосов
/ 08 марта 2013

Другие уже ответили, как решить вашу проблему, поэтому я не буду повторять то, что уже было сказано, но я скажу так: вам, вероятно, следует найти способ решения ваших проблем, не зная счетчика набора результатов дочитая результаты.

Существует очень немного обстоятельств, когда счетчик строк действительно необходим перед чтением результирующего набора, особенно в таком языке, как Java.Единственный случай, когда я думаю о том, где счетчик строк необходим, - это когда количество строк - это единственные данные, которые вам нужны (в этом случае запрос на подсчет будет лучше).В противном случае вам лучше использовать объект-оболочку для представления данных таблицы и хранить эти объекты в динамическом контейнере, таком как ArrayList.Затем, после того как набор результатов будет повторен, вы можете получить счетчик списка массивов.Для каждого решения, которое требует знания счетчика строк перед чтением набора результатов, вы, вероятно, можете придумать решение, которое делает это, не зная счетчика строк перед чтением без особых усилий.Думая о решениях, которые обходят необходимость знать количество строк перед обработкой, вы избавляете ResultSet от необходимости прокрутки до конца набора результатов, а затем обратно к началу (что может быть ОЧЕНЬ дорогой операцией для больших наборов результатов),

Теперь, конечно, я не говорю, что никогда не бывает ситуаций, когда вам может понадобиться количество строк перед чтением набора результатов.Я просто говорю, что в большинстве случаев, когда люди думают, что им нужно количество результирующих наборов до их чтения, они, вероятно, этого не делают, и стоит потратить 5 минут, чтобы подумать, есть ли другой способ.

Просто хотел предложить свои 2 цента по теме.

2 голосов
/ 25 октября 2011

Большинство драйверов поддерживают только набор результатов перенаправления - поэтому методы, такие как last, beforeFirst и т. Д., Не поддерживаются.

Первый подход подходит, если вы также получаете данные в том же цикле - иначе resultSet уже былповторяется и не может быть использован снова.

В большинстве случаев требуется получить количество строк, которое будет возвращать запрос, без выборки строк.Итерация по набору результатов для нахождения количества строк практически идентична обработке данных.Вместо этого лучше сделать другой запрос count (*).

2 голосов
/ 25 октября 2011

Ваша функция вернет размер ResultSet, но его курсор будет установлен после последней записи, поэтому, не перематывая его, вызывая beforeFirst (), first () или previous (), вы не сможете прочитать его строки и методы перемотки не будут работать только с перенаправлением ResultSet (вы получите то же исключение, что и во втором фрагменте кода).

1 голос
/ 29 марта 2017

ResultSet имеет свои методы, которые перемещают курсор вперед и назад в зависимости от предоставленной опции. По умолчанию это движение вперед (тип результата TYPE_FORWARD_ONLY). Если CONSTANTS не указывает на прокручиваемость и обновление набора результатов должным образом, вы можете получить ошибку. Например. позапрошлый() Этот метод не имеет эффекта, если результирующий набор не содержит строк. Выдает ошибку, если это не TYPE_FORWARD_ONLY.

Лучший способ проверить, были ли выбраны пустые строки --- Просто вставить новую запись после проверки несуществования

if( rs.next() ){

   Do nothing
} else {
  No records fetched!
}

См. здесь

...