web-dev-qa-db-fra.com

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 retourne un entier contenant 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!

59
Tiwaz89

Si vous avez accès à l'instruction préparée qui aboutit à cet ensemble de résultats, vous pouvez utiliser

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

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

En règle générale, toutefois, les curseurs de transfert et de rembobinage peuvent s'avérer très inefficaces pour des ensembles de résultats volumineux. Une autre option de 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 ...
54
Lukas Eder

votre code de création d'instructions SQL 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 pour les ensembles de résultats de transmission uniquement" le code d'exception ci-dessus change avec 

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

31
Fathah Rehman P
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, qui donne une erreur telle que TYPE_FORWARD_ONLY utilise cette solution.

SQLite ne prend pas en charge JDBC.

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

Donc, à cette époque, utilisez cette solution.

Merci..

22
Java Man

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

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
The01Guy

Si vous avez table et que vous stockez l'ID en tant qu'incrément principal et incrément automatique, cela fonctionnera. 

Exemple de code pour obtenir le nombre total de lignes http://www.Java2s.com/Tutorial/Java/0340__Database/GettheNumberofRowsinaDatabaseTable.htm

Ci-dessous 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", "");
  }
}
3
anand

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

Il existe très peu de circonstances dans lesquelles le nombre de lignes est réellement nécessaire avant de lire le jeu de résultats, en particulier dans un langage tel que Java. Le seul cas auquel je pense où un nombre de lignes serait nécessaire est lorsque le nombre de lignes est la seule donnée dont vous avez besoin (auquel cas une requête de nombre serait supérieure). Autrement, il vaut mieux utiliser un objet wrapper pour représenter vos données de table et stocker ces objets dans un conteneur dynamique tel que 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 nécessitant de connaître le nombre de lignes avant de lire le jeu de résultats, vous pouvez probablement penser à une solution qui le fait sans connaître le nombre de lignes avant de lire sans trop d'effort. En pensant aux solutions qui évitent de connaître le nombre de lignes avant le traitement, vous éviterez au ResultSet de déranger le défilement jusqu'à la fin du jeu de résultats, puis de revenir au début (ce qui peut être une opération TRES chère pour des jeux de résultats volumineux). . 

Bien entendu, 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 simplement que dans la plupart des cas, quand les gens pensent qu'ils ont besoin du nombre de résultats avant de le lire, ils n'en ont probablement pas et il vaut la peine de prendre 5 minutes pour se demander s'il existe un autre moyen.

Je voulais juste offrir mes 2 cents sur le sujet.

2
aeskreis

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

2
socha23

La plupart des pilotes ne prennent en charge que les résultats, de sorte que les méthodes 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 plus être utilisé.

Dans la plupart des cas, l'exigence consiste à obtenir le nombre de lignes qu'une requête renvoie sans récupérer les lignes. Le fait de parcourir le jeu de résultats pour trouver le nombre de lignes est presque identique au traitement des données. Il est préférable de faire une autre requête count (*) à la place. 

2
gkamal

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 avance (type de résultats TYPE_FORWARD_ONLY). Sauf si CONSTANTS indique correctement Défilement et Mise à jour du jeu de résultats, il est possible que vous obteniez une erreur . E.g. beforeLast () Cette méthode n'a aucun effet si le jeu de résultats ne contient aucune ligne . Lance une erreur s'il ne s'agit pas de TYPE_FORWARD_ONLY.

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

if( rs.next() ){

   Do nothing
} else {
  No records fetched!
}

Voir ici

1
Yergalem

Voici un code qui évite que le nombre instancie un tableau, mais utilise plutôt ArrayList et, juste avant le retour, convertit ArrayList en type de tableau requis.

Notez que la classe Supervisor implémente ici l'interface ISupervisor, mais qu'en Java vous ne pouvez pas transtyper d'objet [] (la méthode plain toArray () de ArrayList renvoie) à ISupervisor [] doivent parcourir tous les éléments de la liste et remplir le tableau de résultats.

/**
 * 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
George Birbilis

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
Nico