Isso não deveria ser uma operação bastante direta? No entanto, vejo que não há um método size()nem length().
Isso não deveria ser uma operação bastante direta? No entanto, vejo que não há um método size()nem length().
Respostas:
Faça uma SELECT COUNT(*) FROM ...consulta em seu lugar.
OU
int size =0;
if (rs != null)
{
rs.last(); // moves cursor to the last row
size = rs.getRow(); // get row id
}
Em qualquer um dos casos, você não precisará fazer um loop sobre os dados inteiros.
select count?
ResultSet#last()não funciona em todos os tipos de ResultSetobjetos, você precisa ter certeza de que usa um que seja ResultSet.TYPE_SCROLL_INSENSITIVEouResultSet.TYPE_SCROLL_SENSITIVE
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
}
getRow()funciona para o TYPE_FORWARD_ONLYResultSets e beforeFirst()gera erros para eles. Esta resposta não está com defeito então?
ps=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
Bem, se você tem um ResultSettipo, ResultSet.TYPE_FORWARD_ONLYdeseja mantê-lo dessa maneira (e não mudar para um ResultSet.TYPE_SCROLL_INSENSITIVEou ResultSet.TYPE_SCROLL_INSENSITIVEpara poder usá-lo .last()).
Sugiro um hack muito agradável e eficiente, no qual você adiciona uma primeira linha falsa / falsa no topo, contendo o número de linhas.
Exemplo
Digamos que sua consulta seja a seguinte
select MYBOOL,MYINT,MYCHAR,MYSMALLINT,MYVARCHAR
from MYTABLE
where ...blahblah...
e sua saída se parece
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]
Basta refatorar seu código para algo como isto:
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);
Sua saída da consulta agora será algo como
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]
Então você só precisa
if(rs.next())
System.out.println("Recordcount: "+rs.getInt("RECORDCOUNT"));//hack: first record contains the record count
while(rs.next())
//do your stuff
ResultSet.TYPE_FORWARD_ONLY)
int i = 0;
while(rs.next()) {
i++;
}
Eu recebi uma exceção ao usar rs.last()
if(rs.last()){
rowCount = rs.getRow();
rs.beforeFirst();
}
:
java.sql.SQLException: Invalid operation for forward only resultset
é por padrão que é ResultSet.TYPE_FORWARD_ONLY, o que significa que você só pode usarrs.next()
a solução é:
stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet.TYPE_FORWARD_ONLYpara ResultSet.TYPE_SCROLL_INSENSITIVEgeralmente incorre em uma enorme penalidade de desempenho.
SELECT COUNT(*) FROM default_tblantes do SELECT COUNT(*) FROM default_tblque levou menos de 1,5 segundo. Eu testei no banco de dados Derby Embedded 10.11.1.1
A maneira de obter o tamanho do ResultSet, Não há necessidade de usar ArrayList etc
int size =0;
if (rs != null)
{
rs.beforeFirst();
rs.last();
size = rs.getRow();
}
Agora você obterá tamanho. Se desejar imprimir o ResultSet, antes de imprimir, use também a seguinte linha de código,
rs.beforeFirst();
[Consideração de velocidade]
Muitas pessoas aqui sugerem, ResultSet.last()mas para isso você precisaria abrir a conexão, ResultSet.TYPE_SCROLL_INSENSITIVEpois o banco de dados incorporado do Derby é até 10 vezes MAIS LENTO que o ResultSet.TYPE_FORWARD_ONLY.
De acordo com meus microtestes para bancos de dados Derby e H2 incorporados, é significativamente mais rápido ligar SELECT COUNT(*)antes do seu SELECT.
É uma maneira simples de fazer contagem de linhas.
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
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);
Eu verifiquei o valor do tempo de execução da interface ResultSet e descobri que era praticamente um ResultSetImpl o tempo todo. ResultSetImpl tem um método chamado getUpdateCount()que retorna o valor que você está procurando.
Este exemplo de código deve ser suficiente:
ResultSet resultSet = executeQuery(sqlQuery);
double rowCount = ((ResultSetImpl)resultSet).getUpdateCount()
Sei que o downcasting geralmente é um procedimento inseguro, mas esse método ainda não me falhou.
java.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp.DelegatingResultSet cannot be cast to com.mysql.jdbc.ResultSetImpl
Hoje, usei essa lógica porque não sei obter a contagem do 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();
Eu estava tendo o mesmo problema. Usando ResultSet.first()desta maneira logo após a execução resolvê-lo:
if(rs.first()){
// Do your job
} else {
// No rows take some actions
}
Documentação ( link ):
boolean first() throws SQLExceptionMove o cursor para a primeira linha deste
ResultSetobjeto.Devoluções:
truese o cursor estiver em uma linha válida;falsese não houver linhas no conjunto de resultadosLances:
SQLException- se ocorrer um erro de acesso ao banco de dados; esse método é chamado em um conjunto de resultados fechado ou o tipo de conjunto de resultados éTYPE_FORWARD_ONLY
SQLFeatureNotSupportedException- se o driver JDBC não suportar este métodoDesde a:
1.2.
A abordagem mais fácil, execute a consulta Count Count (*), faça resultSet.next () para apontar para a primeira linha e, em seguida, faça resultSet.getString (1) para obter a contagem. Código:
ResultSet rs = statement.executeQuery("Select Count(*) from your_db");
if(rs.next()) {
int count = rs.getString(1).toInt()
}
Atribua um nome à coluna ..
String query = "SELECT COUNT(*) as count FROM
Faça referência a essa coluna do objeto ResultSet para um int e faça sua lógica a partir daí.
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.");
}
}