Cela ne devrait-il pas être une opération assez simple? Cependant, je constate qu’il n’ya ni méthode size()
ni length()
.
Faites une requête SELECT COUNT(*) FROM ...
à la place.
OR
int size =0;
if (rs != null)
{
rs.last(); // moves cursor to the last row
size = rs.getRow(); // get row id
}
Dans les deux cas, vous n’aurez pas à parcourir toutes les données.
ResultSet rs = ps.executeQuery();
int rowcount = 0;
if (rs.last()) {
rowcount = rs.getRow();
rs.beforeFirst(); // not rs.first() because the rs.next() below will move on, missing the first element
}
while (rs.next()) {
// do your standard per row stuff
}
Eh bien, si vous avez une ResultSet
de type ResultSet.TYPE_FORWARD_ONLY
vous voulez le conserver ainsi (et not pour passer à un ResultSet.TYPE_SCROLL_INSENSITIVE
ou à un ResultSet.TYPE_SCROLL_INSENSITIVE
afin de pouvoir utiliser .last()
).
Je suggère un hack très agréable et efficace, où vous ajoutez une première ligne fausse/bidon en haut contenant le nombre de lignes.
Exemple
Disons que votre requête est la suivante
select MYBOOL,MYINT,MYCHAR,MYSMALLINT,MYVARCHAR
from MYTABLE
where ...blahblah...
et votre sortie ressemble à
true 65537 "Hey" -32768 "The quick brown fox"
false 123456 "Sup" 300 "The lazy dog"
false -123123 "Yo" 0 "Go ahead and jump"
false 3 "EVH" 456 "Might as well jump"
...
[1000 total rows]
Refactorisez simplement votre code en quelque chose comme ceci:
Statement s=myConnection.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
String from_where="FROM myTable WHERE ...blahblah... ";
//h4x
ResultSet rs=s.executeQuery("select count(*)as RECORDCOUNT,"
+ "cast(null as boolean)as MYBOOL,"
+ "cast(null as int)as MYINT,"
+ "cast(null as char(1))as MYCHAR,"
+ "cast(null as smallint)as MYSMALLINT,"
+ "cast(null as varchar(1))as MYVARCHAR "
+from_where
+"UNION ALL "//the "ALL" part prevents internal re-sorting to prevent duplicates (and we do not want that)
+"select cast(null as int)as RECORDCOUNT,"
+ "MYBOOL,MYINT,MYCHAR,MYSMALLINT,MYVARCHAR "
+from_where);
Le résultat de votre requête sera maintenant quelque chose comme
1000 null null null null null
null true 65537 "Hey" -32768 "The quick brown fox"
null false 123456 "Sup" 300 "The lazy dog"
null false -123123 "Yo" 0 "Go ahead and jump"
null false 3 "EVH" 456 "Might as well jump"
...
[1001 total rows]
Donc vous devez juste
if(rs.next())
System.out.println("Recordcount: "+rs.getInt("RECORDCOUNT"));//hack: first record contains the record count
while(rs.next())
//do your stuff
int i = 0;
while(rs.next()) {
i++;
}
J'ai eu une exception lors de l'utilisation de rs.last()
if(rs.last()){
rowCount = rs.getRow();
rs.beforeFirst();
}
:
Java.sql.SQLException: Invalid operation for forward only resultset
c'est par défaut ResultSet.TYPE_FORWARD_ONLY
, ce qui signifie que vous ne pouvez utiliser que rs.next()
la solution est la suivante:
stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
C'est un moyen simple de compter les lignes.
ResultSet rs = job.getSearchedResult(stmt);
int rsCount = 0;
//but notice that you'll only get correct ResultSet size after end of the while loop
while(rs.next())
{
//do your other per row stuff
rsCount = rsCount + 1;
}//end while
[Considération de vitesse]
Ici, beaucoup de gens suggèrent ResultSet.last()
, mais pour cela, vous devez ouvrir une connexion sous la forme ResultSet.TYPE_SCROLL_INSENSITIVE
qui, pour la base de données intégrée Derby, est jusqu'à 10 fois PLUS LENT que ResultSet.TYPE_FORWARD_ONLY
.
Selon mes micro-tests pour les bases de données Derby et H2 intégrées, il est beaucoup plus rapide d'appeler SELECT COUNT(*)
avant votre SELECT.
La façon d'obtenir la taille de ResultSet, pas besoin d'utiliser ArrayList, etc.
int size =0;
if (rs != null)
{
rs.beforeFirst();
rs.last();
size = rs.getRow();
}
Maintenant, vous aurez la taille, et si vous voulez imprimer le ResultSet, avant d’imprimer utilisez aussi la ligne de code suivante,
rs.beforeFirst();
String sql = "select count(*) from message";
ps = cn.prepareStatement(sql);
rs = ps.executeQuery();
int rowCount = 0;
while(rs.next()) {
rowCount = Integer.parseInt(rs.getString("count(*)"));
System.out.println(Integer.parseInt(rs.getString("count(*)")));
}
System.out.println("Count : " + rowCount);
}
J'ai vérifié la valeur d'exécution de l'interface ResultSet et découvert qu'il s'agissait plutôt d'un ResultSetImpl tout le temps. ResultSetImpl a une méthode appelée getUpdateCount()
qui renvoie la valeur que vous recherchez.
Cet exemple de code devrait suffire: ResultSet resultSet = executeQuery(sqlQuery);
double rowCount = ((ResultSetImpl)resultSet).getUpdateCount()
Je réalise que le downcasting est généralement une procédure dangereuse, mais cette méthode ne m’a pas encore manqué.
Aujourd'hui, j'ai utilisé cette logique pour laquelle je ne sais pas obtenir le décompte de RS.
int chkSize = 0;
if (rs.next()) {
do { ..... blah blah
enter code here for each rs.
chkSize++;
} while (rs.next());
} else {
enter code here for rs size = 0
}
// good luck to u.
theStatement=theConnection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet theResult=theStatement.executeQuery(query);
//Get the size of the data returned
theResult.last();
int size = theResult.getRow() * theResult.getMetaData().getColumnCount();
theResult.beforeFirst();
Donnez un nom à la colonne ..
String query = "SELECT COUNT(*) as count FROM
Référencez cette colonne de l'objet ResultSet dans un int et faites votre logique à partir de là.
PreparedStatement statement = connection.prepareStatement(query);
statement.setString(1, item.getProductId());
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
int count = resultSet.getInt("count");
if (count >= 1) {
System.out.println("Product ID already exists.");
} else {
System.out.println("New Product ID.");
}
}
J'avais le même problème. Utiliser ResultSet.first()
de cette manière juste après l'exécution l'a résolu:
if(rs.first()){
// Do your job
} else {
// No rows take some actions
}
Documentation ( lien ):
boolean first() throws SQLException
Déplace le curseur sur la première ligne de cet objet
ResultSet
.Résultats:
true
si le curseur est sur un .__ valide. rangée;false
s'il n'y a pas de lignes dans le jeu de résultatsLance:
SQLException
- si une erreur d'accès à la base de données se produit; cette méthode est appelée sur un jeu de résultats fermé ou le type de jeu de résultats estTYPE_FORWARD_ONLY
SQLFeatureNotSupportedException
- si le pilote JDBC ne prend pas en charge cette méthodePuisque:
1.2