Comment obtenir le nombre de lignes en utilisant ResultSet en Java?

J'essaie de créer une méthode simple qui reçoit un ResultSet en tant que paramètre et renvoie un int qui contient le nombre de lignes du ResultSet. Est - ce une façon valable de le faire ou pas tellement?

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

J'ai essayé ceci:

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

Mais j'ai eu une erreur en disant com.microsoft.sqlserver.jdbc.SQLServerException: The requested operation is not supported on forward only result sets.

Merci d'avance pour les pointeurs!

57
demandé sur Arpit Porwal 2011-10-25 12:16:10

13 réponses

Si vous avez accès à l'instruction préparée qui aboutit à ce resultset, vous pouvez utiliser

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

Cela prépare votre déclaration de manière à pouvoir rembobiner le curseur. Ceci est également documenté dans le ResultSet Javadoc

En général, cependant, le transfert et le rembobinage des curseurs peuvent être très inefficaces pour les grands ensembles de résultats. Une autre option dans SQL Server serait de calculer le nombre total de lignes directement dans votre instruction SQL:

SELECT my_table.*, count(*) over () total_rows
FROM my_table
WHERE ...
53
répondu Lukas Eder 2018-10-06 08:25:39

Votre instruction sql créant du code peut être comme

statement = connection.createStatement();

Pour résoudre " com.Microsoft.sqlserver.jdbc.SQLServerException: L'opération demandée n'est pas prise en charge sur les ensembles de résultats forward only " exception change above code with

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

Après le changement ci-dessus, vous pouvez utiliser

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

Pour obtenir le nombre de lignes

26
répondu Fathah Rehman P 2012-10-27 17:25:15
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).");

Parfois, JDBC ne prend pas en charge la méthode suivante donne une erreur comme 'TYPE_FORWARD_ONLY' utilisez cette solution

Sqlite ne prend pas en charge dans JDBC.

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

Donc, à ce moment-là, utilisez cette solution.

Merci..

22
répondu Java Man 2014-01-29 05:16:44

Faites une requête SELECT COUNT(*) FROM ... à la place.

6
répondu Suganthan Madhavan Pillai 2014-01-29 05:37:32

Je viens de faire une méthode getter.

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;
}
5
répondu The01Guy 2013-05-24 04:54:40

Votre fonction retournera la taille d'un ResultSet, mais son curseur sera défini après le dernier enregistrement, donc sans le rembobiner en appelant beforeFirst(), first() ou previous() vous ne pourrez pas lire ses lignes, et les méthodes de rembobinage ne fonctionneront pas avec forward only ResultSet (vous obtiendrez la même exception que dans votre deuxième fragment de code).

2
répondu socha23 2011-10-25 08:20:47

La plupart des pilotes prennent en charge forward only resultset - donc la méthode comme last, beforeFirst etc ne sont pas prises en charge.

La première approche est appropriée si vous obtenez également les données dans la même boucle - sinon le resultSet a déjà été itéré et ne peut pas être utilisé à nouveau.

Dans la plupart des cas, l'exigence est d'obtenir le nombre de lignes qu'une requête retournerait sans récupérer les lignes. Parcourir le jeu de résultats pour trouver le nombre de lignes est presque identique au traitement des données. Il est mieux vaut faire une autre requête count(*) à la place.

2
répondu gkamal 2011-10-25 08:22:32

D'autres ont déjà répondu comment résoudre votre problème, donc je ne vais pas répéter ce qui a déjà été dit, Mais je vais dire ceci: vous devriez probablement trouver un moyen de résoudre vos problèmes sans connaître le nombre de résultats avant de lire les résultats.

Il y a très peu de circonstances où le nombre de lignes est réellement nécessaire avant de lire le jeu de résultats, en particulier dans un langage comme Java. Le seul cas auquel je pense où un nombre de lignes serait nécessaire est quand la ligne count est la seule donnée dont vous avez besoin (auquel cas une requête count serait supérieure). Sinon, il vaut mieux utiliser un objet wrapper pour représenter les données de votre table et stocker ces objets dans un conteneur dynamique tel Qu'un ArrayList. Ensuite, une fois que le jeu de résultats a été itéré, vous pouvez obtenir le nombre de listes de tableaux. Pour chaque solution, qui nécessite de connaître le nombre de lignes avant de lire le jeu de résultats, vous pouvez probablement penser à une solution qui n'est sans savoir que le nombre de lignes avant lecture sans trop d'effort. En pensant à des solutions qui contournent le besoin de connaître le nombre de lignes avant le traitement, vous enregistrez le ResultSet le problème de défilement à la fin du jeu de résultats, puis au début (ce qui peut être une opération très coûteuse pour les grands ensembles de résultats).

Maintenant, bien sûr, je ne dis pas qu'il n'y a jamais de situations où vous pourriez avoir besoin du nombre de lignes avant de lire un jeu de résultats. Je dis juste que dans la plupart des circonstances, quand les gens pensent qu'ils ont besoin de la le jeu de résultats compte avant de le lire, ils ne le font probablement pas, et il vaut la peine de prendre 5 minutes pour réfléchir s'il y a un autre moyen.

Je voulais Juste offrir mes 2 cents sur le sujet.

2
répondu aeskreis 2013-03-08 17:27:37

Si vous avez une table et stockez l'ID en tant qu'incrément primaire et automatique, cela fonctionnera

Exemple de code pour obtenir le nombre total de ligneshttp://www.java2s.com/Tutorial/Java/0340__Database/GettheNumberofRowsinaDatabaseTable.htm

Ci-dessous est le code

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
répondu anand 2015-03-03 20:09:57

Le ResultSet a ses méthodes qui déplacent le curseur d'avant en arrière en fonction de l'option fournie. Par défaut, il se déplace vers L'avant(TYPE_FORWARD_ONLY resultset type). À moins que les constantes indiquant la défilement et la mise à jour du resultset correctement, vous pourriez finir par obtenir une erreur. E. g. beforeLast() Cette méthode n'a aucun effet si le jeu de résultats ne contient aucune ligne. Renvoie une erreur si ce n'est pas TYPE_FORWARD_ONLY.

La meilleure façon de vérifier si les lignes vides ont été récupérées - - - juste pour insérer un nouveau enregistrement après vérification de la non-existence

if( rs.next() ){

   Do nothing
} else {
  No records fetched!
}

Voir ici

1
répondu Yergalem 2017-03-29 14:17:24

Voici un code qui évite d'obtenir le compte pour instancier un tableau, mais utilise un ArrayList à la place et juste avant de retourner convertit le ArrayList au type de tableau nécessaire.

Notez que la classe Supervisor implémente ici l'interface ISupervisor, mais en Java, vous ne pouvez pas convertir object [] (la méthode ToArray() de ArrayList retourne) à ISupervisor [] (comme je pense que vous pouvez le faire en C#), vous devez donc parcourir tous les éléments de la liste et remplir le tableau de résultat.

/**
 * Get Supervisors for given program id
 * @param connection
 * @param programId
 * @return ISupervisor[]
 * @throws SQLException
 */
public static ISupervisor[] getSupervisors(Connection connection, String programId)
  throws SQLException
{
  ArrayList supervisors = new ArrayList();

  PreparedStatement statement = connection.prepareStatement(SQL.GET_SUPERVISORS);
  try {
    statement.setString(SQL.GET_SUPERVISORS_PARAM_PROGRAMID, programId);
    ResultSet resultSet = statement.executeQuery();  

    if (resultSet != null) {
      while (resultSet.next()) {
        Supervisor s = new Supervisor();
        s.setId(resultSet.getInt(SQL.GET_SUPERVISORS_RESULT_ID));
        s.setFirstName(resultSet.getString(SQL.GET_SUPERVISORS_RESULT_FIRSTNAME));
        s.setLastName(resultSet.getString(SQL.GET_SUPERVISORS_RESULT_LASTNAME));
        s.setAssignmentCount(resultSet.getInt(SQL.GET_SUPERVISORS_RESULT_ASSIGNMENT_COUNT));
        s.setAssignment2Count(resultSet.getInt(SQL.GET_SUPERVISORS_RESULT_ASSIGNMENT2_COUNT));
        supervisors.add(s);
      }
      resultSet.close();
    }
  } finally {
    statement.close();
  }

  int count = supervisors.size();
  ISupervisor[] result = new ISupervisor[count];
  for (int i=0; i<count; i++)
    result[i] = (ISupervisor)supervisors.get(i);
  return result;
}
0
répondu George Birbilis 2013-07-25 11:59:42

Les Deux options suivantes ont fonctionné pour moi:

1) une fonction qui renvoie le nombre de lignes dans votre ResultSet.

private int resultSetCount(ResultSet resultSet) throws SQLException{
    try{
        int i = 0;
        while (resultSet.next()) {
            i++;
        }
        return i;
    } catch (Exception e){
       System.out.println("Error getting row count");
       e.printStackTrace();
    }
    return 0;
}

2) créez une deuxième instruction SQL avec L'option COUNT.

0
répondu Nico 2016-02-09 11:20:26

À Partir de http://docs.oracle.com/javase/1.4.2/docs/api/java/sql/ResultSetMetaData.html

 ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM TABLE2");
 ResultSetMetaData rsmd = rs.getMetaData();
 int numberOfColumns = rsmd.getColumnCount();

Un ResultSet contient des métadonnées qui donnent le nombre de lignes.

-7
répondu igor 2012-01-31 16:59:02