ResultSet retorna menos registros do que deveria

27 respostas
M

Olá pessoALL,

Estou com o seguinte problema: Tenho uma consulta ao banco de dados que retorna 573 registros, porém quando executo meu programa o ResultSet que faz essa consulta retorna apenas 512 registros. Alguém tem ideia do que possa ser?

Valew…

Marcelo.

27 Respostas

celso.martins

Cara, tenta fornecer mais informações. Como você está implementando a camada de persistência?

Em tempo, procure analisar o registro está faltando. Se ele tem alguma particularidade.

Nesse sentido, uma ferramenta como o UltraEdit com o seu UltraCompare, pode ajudar.

M

A camada de persistência não usa nenhum framework específico, é feita por jdbc mesmo.

Os registros faltantes não tem nenhuma particularidade, são iguais a todos os outros.

Essa tá difícil hein.

Vlw. Marcelo.

celso.martins

Esse registro não seria o primeiro? Ou o último?

Se for, já podemos ter um caminho para a análise.

Posta teu código aí.

Obs: Não esqueça da tag code.

T

512 é um número engraçado, já que é uma potência de 2.
Normalmente buffers são potências de 10 ou potências de 2; provavelmente, em vez de ir lendo os registros em um ArrayList sem voltar para trás e sem ficar contando quantos você vai pegar, você está pegando a contagem (com resultset.last()) e depois está criando um array, o que não é normalmente recomendado, porque você acaba sendo obrigado a usar um ResultSet não muito eficiente (são os que permitem o “scrolling”), e se houver algum bug no driver JDBC, você pode acabar tendo um erro como o que você teve.

celso.martins

thingol:
512 é um número engraçado, já que é uma potência de 2.
Normalmente buffers são potências de 10 ou potências de 2; provavelmente, em vez de ir lendo os registros em um ArrayList sem voltar para trás e sem ficar contando quantos você vai pegar, você está pegando a contagem (com resultset.last()) e depois está criando um array, o que não é normalmente recomendado, porque você acaba sendo obrigado a usar um ResultSet não muito eficiente (são os que permitem o “scrolling”), e se houver algum bug no driver JDBC, você pode acabar tendo um erro como o que você teve.

Mas não tinha percebido a peculiaridade do 512.

De qualquer maneira, seria interessante fazer um contador dentro do while para ter certeza. Ou se estiver jogando em um List, pegar o tamanho que ficou esse List.

M

Não é apenas um registro que falta. São 61 registros que o ResultSet não traz e que são retornados executando a mesma consulta pelo plugin QuantumDB.

celso.martins

Como é que você está chegando a esse 512?

M

No debug do eclipse, nas propriedades do ResultSet, em numRows = 512. Em uma outra consulta que retorna 40 registros os números batem.

celso.martins

Você tem permissão para passar o código do método que está responsável por isso?

M

O código do método que retorna o ResultSet problemático é este:

private ResultSet getAtividadesFuncao(char ordenacao, char buscarAtivas,
                                          long idOrgao) {

        if ((idOrgao == -1) && (buscarAtivas == 'N')) {
            sql = "SELECT AFUN_CODG, AFUN_DESC, AFUN_STAT_ATIVO "
                + "FROM ATIVIDADES_FUNCAO";
        } else if ((idOrgao == -1) && (buscarAtivas == 'S')) {
            sql = "SELECT AFUN_CODG, AFUN_DESC, AFUN_STAT_ATIVO "
                + "FROM ATIVIDADES_FUNCAO "
                + "WHERE AFUN_STAT_ATIVO = 'S'";
        } else if ((idOrgao != -1) && (buscarAtivas == 'N')) {
            sql = "SELECT AFUN_CODG, AFUN_DESC, AFUN_STAT_ATIVO "
                + "FROM ATIVIDADES_FUNCAO, ATIVIDADES_FUNCAO_ORGAOS "
                + "WHERE AFOR_AFUN_CODG = AFUN_CODG "
                + "AND AFOR_ORRH_IDEN = ?";
        } else if ((idOrgao != -1) && (buscarAtivas == 'S')) {
            sql = "SELECT AFUN_CODG, AFUN_DESC, AFUN_STAT_ATIVO "
                + "FROM ATIVIDADES_FUNCAO, ATIVIDADES_FUNCAO_ORGAOS "
                + "WHERE AFOR_AFUN_CODG = AFUN_CODG "
                + "AND AFOR_ORRH_IDEN = ?"
                + " AND AFUN_STAT_ATIVO = 'S'";
        }

        switch (ordenacao){
            case 'C':   sql = sql + " ORDER BY AFUN_CODG";
                break;
            case 'D':   sql = sql + " ORDER BY AFUN_DESC";
                break;
            case 'S':   sql = sql + " ORDER BY AFUN_STAT_ATIVO DESC";
                break;
        }

        //limpa os atributos da classe
        this.limparPropriedades();

        try {
            //Prepara SQL
            PreparedStatement pstmt = objTransacao.prepararSQL(sql);
            if (pstmt == null) {
                erroCodigo = objTransacao.getErroCodigo();
                erroMensagem = objTransacao.getErroMensagem();
                return null;
            }
            //Seta parametros
            if (idOrgao != -1) {
                pstmt.setLong(1, idOrgao);
            }
            ResultSet rset = objTransacao.consultarSQL(pstmt);
            if (rset == null) {
                erroMensagem = objTransacao.getErroMensagem();
                erroCodigo = objTransacao.getErroCodigo();
                return null;
            }
            return rset;
        } catch (SQLException e) {
            erroMensagem = e.getMessage();
            erroCodigo = e.getErrorCode();
            return null;
        }
    }

O código responsável por executar o SQL é este:

public final CachedRowSet consultarSQL(PreparedStatement pstmt, boolean fecharPstmt) {
        erroCodigo   = 0;
        erroMensagem = "";
        ResultSet rset = null;
        CachedRowSet crset = null;
        try {
            rset = pstmt.executeQuery();
            try{
                crset = new CachedRowSetImpl();
            }catch (Exception e) {
                crset = new CachedRowSetImpl();
            }
            crset.setReadOnly(true);
            crset.populate(rset);
            this.verificarLimite(crset);
            rset.close();
        }
        catch (SQLException e) {
            erroCodigo = e.getErrorCode();
            erroMensagem = "Erro na consulta SQL : " + e.getMessage();
            return null;
        } finally {
            try {
                if (pstmt != null && fecharPstmt) {
                    pstmt.close();
                }
            } catch (SQLException e) {
                erroMensagem = "Erro no fechamento do Prepared Statement : " + e.getMessage();
            }
        }

        return crset;
    }
R

Você (ou algum componente JDBC que esteja usando) limitou o número máximo de registros que poderiam ser retornados?

http://java.sun.com/javase/6/docs/api/java/sql/Statement.html#setMaxRows(int)

Também pode haver uma limitação de FetchSize:

http://www.exampledepot.com/egs/java.sql/GetFetchSize.html

celso.martins

O que eu te aconselho, para tentar achar o problema é, em primeiro lugar, pegar o SQL que você está fazendo diretamente no banco, deixa-lo hardcoded em um método mais simples.

Conta esse resultado com um contador. Dessa forma, você pode caminhar para um problema nas classes do Java ou na sua implementação.

Ainda está muito obscura a localização do problema. Tenta restringir as possibilidades. Faça algo bem simples, como isso aqui:

public void foo() throws SQLException{
		final String sql = " SELECT * FROM xpto ";
		
		Connection con         = null;
		PreparedStatement stmt = null;
		ResultSet rs           = null;
		
		try{
			con  = OracleDAO.getConnection();
			stmt = con.prepareStatement(sql);
			rs   = stmt.executeQuery();
			
			int contador = 0;
			while (rs.next()){
				contador++;
			}
			
		}finally{
			rs.close();
			stmt.close();
			con.close();
		}
	}
M

Ok pessoal, valeu pelas dicas.

Vou dar uma olhada mais aprofundada nesse código aí (que nem fui eu quem fiz, o que torna mais difícil achar o problema).

Obrigado.

jgbt

ola,
se consultas que retornam menos registros funcionam, com certeza alguma coisa esta limitando o numero de registros.
meu palpite é essa linha:

this.verificarLimite(crset);

o que faz esse metodo verificarLimite?

[]´s

M

Também pensei que pudesse ser esse método, mas ele só verifica quantos registros foram retornados e imprime um alerta no log caso retorne mais de 2000 registros, nenhum limite quanto ao número de registros retornados é imposto de fato.

jgbt

Ola,
qual banco e driver vc esta usando?
Talves uma olhada no driver jdbc ajude.

mas antes disso faça o teste do contador no ResultSet e veja quantas linhas sao retornadas.

[]´s

M

Usamos Oracle. O driver é oracle.jdbc.OracleDriver.

Já fiz o teste do contador e realmente são retornadas apenas 512 linhas, mas quando consulto pelo plugin do eclipse QuantumDB são retornadas 573 linhas.

jgbt

marcelodias:
Usamos Oracle. O driver é oracle.jdbc.OracleDriver.

Já fiz o teste do contador e realmente são retornadas apenas 512 linhas, mas quando consulto pelo plugin do eclipse QuantumDB são retornadas 573 linhas.

Realmente estranho.
Ja usei muito Oracle ate a versão 9i, na epoca com o classes12.jar como driver e posso te garantir que fazia consultas com bem mais de 521 registros.
se vc imprmir o sql que ira para o banco e executa-lo em outra ferramenta tmb retorna 573 linhas?

[]´s

M

Retorna sim. Usamos ojdbc14.jar. Existem consultas com mais de 2 mil registros que faz normalmente, mas essa não sei o que ta acontecendo.

jgbt

putz… realmente muito estranho isso. Em algum lugar isso deve estar sendo limitado.
A unica sugestão que ainda posso te dar é debugar linha a linha. Caso vc não encontre nada, faz um debug no codigo do driver jdbc.
Boa sorte.

[]´s

M

Valeu pela ajuda galera.

Vou tentar investigar minuciosamente o que ta acontecendo com essa bagaça aqui. :?

T

Você está usando um com.sun…CachedRowsetImpl ou um oracle…CachedRowSet? Os exemplos da Oracle normalmente usam o segundo, talvez o primeiro (que é específico da Sun) não funcione direito.

M

Pessoal,

Descobri o problema. Não era nada com o ResultSet. O problema é que meu sistema estava configurado para um banco de dados diferente do que é usado para as consultas no SQL Developer, e o erro era gerado por uma inconsistência de dados e não de implementação. Ufa, até descobrir isso foi um custo… Gostaria de agradecer a todos que se atentaram ao meu problema.

Valew… T+!

Marcelo.

T

O velho problema do “string de conexão apontando para o banco errado” :stuck_out_tongue:

celso.martins

Isso sempre acontece. =)

Cuidado para não dar um delete from em produção achando que está no ambiente de testes.

M

Celso, ainda bem que isso é impossível acontecer… meu acesso é só nos ambientes de desenvolvimento e homologação!! rssrs :stuck_out_tongue:

Valew galera!

T

marcelodias:
Celso, ainda bem que isso é impossível acontecer… meu acesso é só nos ambientes de desenvolvimento e homologação!! rssrs :stuck_out_tongue:

Valew galera!

Tô sabendo… volta e meia você vê clientes que não têm ambientes tão bem separadinhos assim. É bom sempre tomar cuidado, principalmente se for trabalhar em um lugar menos organizado.

Criado 11 de maio de 2009
Ultima resposta 14 de mai. de 2009
Respostas 27
Participantes 5