Qual estrutura usar para colocar o resultado de uma consulta sql?

Preciso colocar o resultado de uma consulta sql em alguma estrutura, pois preciso fazer alguns cálculos antes de imprimir em uma tabela view. Imaginei que o melhor seria usar uma matriz. Porém como eu vou criar a matriz sem saber o numero de linhas que sera retornado?

Obs:

  • Uma das possibilidades que pensei era consultar a primeira vez e dentro do while (rs.next) criar um contador… ao final dele eu teria o numero de linhas. ai criaria a matriz depois disso porem teria q consultar o banco de novo, isso parece custoso…

alguma ideia melhor e mais pratica?

Em vez de uma matriz, use um Collection (como List e seus derivados) e insira os elementos nele no while (next() do resultset). Ao final, todos estarão dentro da lista, e você terá a informação de quantos registros existem.

Abraço.

E como você faria isso em um array? Iria criar um array pra cada coluna da consulta? Cai no mesmo problema.

Se já não está fazendo, é aí que você deve usar classes e objetos. Crie uma classe para representar o tipo retornado na sua query, e insira na lista instâncias dessa classe criadas a partir dessa da consulta. Por exemplo:


class Produto{
  int codigo;
  String descricao;
  float preco;

  public Produto(int c, string d, float p){
    this.codigo = c;
    this.descricao = d;
    this.preco = p;
  }
}

// mais pra frente

String sql = "select codigo, descricao, preco from produto";
ResultSet rs = executarConsulta(sql);

List lista = new ArrayList<Produto>();

while (rs.next()){
  Produto pro = new Produto(rs.getInt(0), rs.getString(1), rs.getFloat(2));
  lista.add(pro);
}

// aqui você usa os resgistros em lista.

Abraço.

Tetei conforme codigo abaixo porem obtive o seguinte erro:
Erro: java.sql.SQLException: After end of result set

ArrayList lista_banco_de_dados = new ArrayList<>();

    try {

        Connection con = Conexao.Conecta();
        PreparedStatement stmt;
        String sql = "SELECT  Veiculos_name_veiculos, sum(litros_abastecidos_abastecimento) as 'litros_abastecidos_abastecimento', max(hodometro_abastecimento) as 'hodometro_abastecimento', sum(valor_total_abastecimento) as 'valor_total_abastecimento', (select min(hodometro_abastecimento) from abastecimento) as 'hodometro_minimo' FROM abastecimento WHERE data_abastecimento >= '0000-01-01' AND data_abastecimento<= '2050-12-12' group by Veiculos_name_veiculos ;";

        stmt = con.prepareStatement(sql);
        ResultSet rs = stmt.executeQuery(sql);

        //Carrega a matriz
        while (rs.next()) {

            lista_banco_de_dados.add(rs);

        }

        for (int i = 0; i < lista_banco_de_dados.size(); i++) {

            System.out.println(" ");
            System.out.println("Linha: " + i);
            System.out.println(lista_banco_de_dados.get(i).getString("Veiculos_name_veiculos"));
            System.out.println(lista_banco_de_dados.get(i).getString("valor_total_abastecimento"));
        }
       

    } catch (Exception e) {

        System.out.println("Erro: " + e);

    }

É correto criar uma classe para retornos de um select do banco de dados? ou é apenas uma gambiarra para funcionar?

É uma opção, e não é uma gambiarra.

Em condições normais, um sistema já terá classes ou estruturas similares, sob as quais você já realiza as ações do sistema. Usar essas mesmas classes para armazenar os dados carregados da base através de um dataset é uma evolução normal. É algo comum em sistemas que usam DAO/DTO (ex: design pattern - Qual a diferença entre DAO e Repository? - Stack Overflow em Português e java - Como funciona o Padrão DAO? - Stack Overflow em Português ).

Obviamente, não serve em todos os casos. E pode ser desnecessário se seu select retorna, por exemplo, apenas 1 registro com uma coluna.

No seu código, você está tentando adicionar o objeto ResultSet rs na lista, enquanto que deveria adicionar instâncias de uma classe que representa os dados retornados, como exemplifiquei anteriormente. Algo como:

// nome exageradamente grande de propósito, pra ser explícito. Sempre ajuste suas classes de acordo
class ResultadoDaConsultaPorDataEVeiculo{
  String Veiculos_name_veiculos;
  float litros_abastecidos_abastecimento;
  float hodometro_abastecimento;
  float hodometro_minimo;

  public ResultadoDaConsultaPorDataEVeiculo(valores para os atributos aqui){
    // preenche os atributos da classe aqui
  }

// getters e setters aqui, SE NECESSÁRIO
}

List<ResultadoDaConsultaPorDataEVeiculo > lista_banco_de_dados = new ArrayList<ResultadoDaConsultaPorDataEVeiculo >();

while (rs.next()) {
 ResultadoDaConsultaPorDataEVeiculo resultado = new ResultadoDaConsultaPorDataEVeiculo (
  rs.getString(0),
  rs.getFloat(1),
  rs.getFloat(2),
  rs.getDate(3),
  ); 

 lista_banco_de_dados.add(resultado);
}

// aqui você faz o for, ou o que mais quiser:

for(ResultadoDaConsultaPorDataEVeiculo  re : lista_banco_de_dados){
  System.out.println(" ");
  System.out.println("Linha: " + i);
  System.out.println(re.getVeiculos_name_veiculos());
  System.out.println(re.getLitros_abastecidos_abastecimento());
  // outros campos
}

Abraço.

1 curtida