Como ter várias sentenças em uma única função

Oi, pessoal.

Estou programando com interface gráfica, mas acho que o pessoal dessa área conseguirá responder a minha dúvida.

Como eu faço para ter várias sentenças em uma única função? O problema é que se eu coloco mais de uma query, por exemplo, na mesma função, fala que o objeto que eu utilizei como resposta já está “closed”.

Eu preciso dessa função para coletar alguns dados do DB. Entre eles o total de produtos cadastrados no DB, total de clientes cadastrados, etc. Então, vou armazena-los todos em um Vector e enviar pra classe que chama ele. Só que ocorre esse erro que e falei quando chamo o método.

Cara pelo que eu entendi você tem várias consultas diferentes dentro de uma mesma string e quer executar tudo de uma vez.
Cara se for isso, não dá pra fazer, você precisa fazer cada uma separada, a não ser que você faça utilizando um union ou seja uma subquery, tirando isso, você vai precisar fazer uma por vez.

ElvisCamilo

Teria como você postar o código pra ajudarmos melhor?
O que você indicou é simples e deve ser algum detalhe na sua implementação
que está atrapalhando.

Até mais!

[quote=Gerson da S. Lima]Cara pelo que eu entendi você tem várias consultas diferentes dentro de uma mesma string e quer executar tudo de uma vez.
Cara se for isso, não dá pra fazer, você precisa fazer cada uma separada, a não ser que você faça utilizando um union ou seja uma subquery, tirando isso, você vai precisar fazer uma por vez.[/quote]

Não é isso. São várias consultas diferentes com objetos distintos guardando a sentença SQL distintos.

Gerson

O que eu tento fazer é o seguinte:

[code] public static String[] pegaDadosIniciais() throws SQLException{

    PreparedStatement objSQLTotProd = objCon.prepareStatement("SELECT COUNT(*) AS TOTPROD FROM TABPRODUTOS");
    ResultSet objRespTotProd = objSQLTotProd.executeQuery();

    PreparedStatement objSQLTotCli = objCon.prepareStatement("SELECT COUNT(*) AS TOTCLI FROM CLIENTES");
    ResultSet objRespTotCli = objSQLTotCli.executeQuery();

    String[] objResposta[];

    //Faz Cast
    objResposta[0] = "" + objRespTotProd.getInt("TOTPROD");
    objResposta[1] = "" + objRespTotCli.getInt("TOTCLI");

    //Obteu os dados com sucesso se não retorna erro
    if(objRespTotProd.next()){
       return objResposta;
    } else {
        throw new SQLException("Falha ao obter estatísticas iniciais.");
    }
}[/code]

A idéia é mais ou menos essa. Só que a função retorna um SQLException falando do “Result set already Closed.”, ou algo assim.

é porque tu tá chamando os resultados antes de dá next no resultset.

Faz assim:

if (objSQLTotProd.next())
objResposta[0] = "" + objRespTotProd.getInt("TOTPROD");

if (objRespTotCli.next())
objResposta[1] = "" + objRespTotCli.getInt("TOTCLI");

if(objResposta.length() > 0) {
return objResposta;
} else {
throw new SQLException("Falha ao obter estatísticas iniciais.");
}

acho q isso resolve teu problema, mas cara, sinceramente essa implementação tá muito extranha. Dá uma pensada melhor, melhora um pouco essa implementação.

abraços

[quote=Gerson da S. Lima]é porque tu tá chamando os resultados antes de dá next no resultset.

Faz assim:

if (objSQLTotProd.next())
objResposta[0] = "" + objRespTotProd.getInt("TOTPROD");

if (objRespTotCli.next())
objResposta[1] = "" + objRespTotCli.getInt("TOTCLI");

if(objResposta.length() > 0) {
return objResposta;
} else {
throw new SQLException("Falha ao obter estatísticas iniciais.");
}

acho q isso resolve teu problema, mas cara, sinceramente essa implementação tá muito extranha. Dá uma pensada melhor, melhora um pouco essa implementação.

abraços
[/quote]

Estranha? Como assim?

[quote=Gerson da S. Lima]é porque tu tá chamando os resultados antes de dá next no resultset.

Faz assim:

if (objSQLTotProd.next())
objResposta[0] = "" + objRespTotProd.getInt("TOTPROD");

if (objRespTotCli.next())
objResposta[1] = "" + objRespTotCli.getInt("TOTCLI");

if(objResposta.length() > 0) {
return objResposta;
} else {
throw new SQLException("Falha ao obter estatísticas iniciais.");
}

acho q isso resolve teu problema, mas cara, sinceramente essa implementação tá muito extranha. Dá uma pensada melhor, melhora um pouco essa implementação.

abraços
[/quote]

Ainda deu o mesmo erro. Eu acho que o problema tá na utilização dos métodos do SQL. :confused:

Algumas considerações:

  • Procure utilizar o valor do resultset logo após rodar o comando no banco.
    Nâo prepare vários resultsets para depois ler o valor 1 a 1.

  • Procure utilizar os tipos de dados corretamente.
    Se retornará com valores inteiros, por que não colocar o tipo de retorno como int[] de uma vez?

  • Evite retornar um conjunto diferente de valores com um array.
    Para ler isto em outro lugar você usará algo como:

  int[] dadosIniciais = pegaDadosIniciais();
  int quantidadeProdutos = dadosIniciais[0];
  int quantidadeClientes = dadosIniciais[1];

Este tipo de código facilita o aparecimento de bugs.
Mudando a ordem dos valores em pegaDadosIniciais tudo pára de funcionar.
Crie uma classe com estas propriedades e retorne a classe no seu método.

  • Procure isolar o código de acesso ao banco do resto da sua aplicação.
    A forma mais comum de se fazer isto é utilizando o padrão DAO.
    Dê uma estudada a respeito.

Se seguir (quase) todas estas considerações e o problema continuar, me responda:

  • Que banco de dados está utilizando?
    Você consegue trazer essas informações com um comando só, mas a sintaxe varia de banco pra banco.

  • Este código que postou é exatamente igual o que está rodando?
    Copiando o código que colocou ele nem compila (mesmo com as alterações sugeridas)

[quote=AbelBueno]Algumas considerações:

  • Procure utilizar o valor do resultset logo após rodar o comando no banco.
    Nâo prepare vários resultsets para depois ler o valor 1 a 1.

  • Procure utilizar os tipos de dados corretamente.
    Se retornará com valores inteiros, por que não colocar o tipo de retorno como int[] de uma vez?

  • Evite retornar um conjunto diferente de valores com um array.
    Para ler isto em outro lugar você usará algo como:

  int[] dadosIniciais = pegaDadosIniciais();
  int quantidadeProdutos = dadosIniciais[0];
  int quantidadeClientes = dadosIniciais[1];

Este tipo de código facilita o aparecimento de bugs.
Mudando a ordem dos valores em pegaDadosIniciais tudo pára de funcionar.
Crie uma classe com estas propriedades e retorne a classe no seu método.

  • Procure isolar o código de acesso ao banco do resto da sua aplicação.
    A forma mais comum de se fazer isto é utilizando o padrão DAO.
    Dê uma estudada a respeito.

Se seguir (quase) todas estas considerações e o problema continuar, me responda:

  • Que banco de dados está utilizando?
    Você consegue trazer essas informações com um comando só, mas a sintaxe varia de banco pra banco.

  • Este código que postou é exatamente igual o que está rodando?
    Copiando o código que colocou ele nem compila (mesmo com as alterações sugeridas)

[/quote]

Sim, já utilizo tudo isso que você citou, inclusive o DAO e só retorno um vetor de String por que vou adicionar para um conjunto de Strings no final, daí daria na mesma, por que eu teria de fazer Cast do mesmo jeito. A idéia de criar uma classe com os dados que eu vou pegar eu tinha ela des de o início, mas como não consegui nem fazer ler os dados que eu quero do BD, não continuei.

Utilizo o Firebird.

O código que eu postei não é igual, por que o que eu tinha eu o retirei, esse daí criei na hora de criar o tópico, mas era assim que eu utilizava. O maior problema é o erro do ResultSet que fala que já está Closed, o resto dá pra arrumar. :confused:

Você tentou a minha primeira sugestão?

Você tentou a minha primeira sugestão?

[/quote]

Sim, utilizei. Assim que eu fazia a pesquisa eu atribuia o valor, mas mesmo assim dava o mesmo problema. Será que cada Statement tem que ficar em um try…catch?

Como ficou o código depois destas alterações?

    public static int[] pegaDadosIniciais() throws SQLException{

        PreparedStatement objSQLTotProd = objCon.prepareStatement("SELECT COUNT(*) AS TOTPROD FROM TABPRODUTOS");
        ResultSet objRespTotProd = objSQLTotProd.executeQuery();

        PreparedStatement objSQLTotCli = objCon.prepareStatement("SELECT COUNT(*) AS TOTCLI FROM CLIENTES");
        ResultSet objRespTotCli = objSQLTotCli.executeQuery();

        int[] resposta = {0,0,0,0,0,0,0,0,0,0,0,0};

        if (objRespTotProd.next()){
            resposta[0] = objRespTotProd.getInt("TOTPROD");
        }

        if (objRespTotCli.next()){
            resposta[1] = objRespTotCli.getInt("TOTCLI");
        }

       return resposta;
    }

Dá o erro: Result set is closed.

Você não falou que tinha feito as alterações que eu sugeri???

Tente isso:

    public static int[] pegaDadosIniciais() throws SQLException{

        int[] resposta = {0,0,0,0,0,0,0,0,0,0,0,0};

        PreparedStatement objSQLTotProd = objCon.prepareStatement("SELECT COUNT(*) AS TOTPROD FROM TABPRODUTOS");
        ResultSet objRespTotProd = objSQLTotProd.executeQuery();
        if (objRespTotProd.next()){
            resposta[0] = objRespTotProd.getInt("TOTPROD");
        }

        PreparedStatement objSQLTotCli = objCon.prepareStatement("SELECT COUNT(*) AS TOTCLI FROM CLIENTES");
        ResultSet objRespTotCli = objSQLTotCli.executeQuery();
        if (objRespTotCli.next()){
            resposta[1] = objRespTotCli.getInt("TOTCLI");
        }
       return resposta;
    }

Movido para o fórum de Persistência.

Cuidado, abra sempre seu tópico no fórum mais específico. Abrir no fórum errado pode fazer com que ele demore muito mais a ser respondido, além de atrair usuários que são bem intencionados, mas não são muito especialistas no assunto.

No caso, você deve procurar o fórum que seja pertinente a sua dúvida. Esse tópico aqui, por exemplo, fala exclusivamente de acesso a dados, e pouco importa a interface final da solução. Por isso, o local mais adequado é mesmo o fórum de persistência. :wink:

[quote=ViniGodoy]Movido para o fórum de Persistência.

Cuidado, abra sempre seu tópico no fórum mais específico. Abrir no fórum errado pode fazer com que ele demore muito mais a ser respondido, além de atrair usuários que são bem intencionados, mas não são muito especialistas no assunto.

No caso, você deve procurar o fórum que seja pertinente a sua dúvida. Esse tópico aqui, por exemplo, fala exclusivamente de acesso a dados, e pouco importa a interface final da solução. Por isso, o local mais adequado é mesmo o fórum de persistência. ;)[/quote]

Hehe. Mas foi justalmente o que eu fiz. Por isso falei que o projeto é com interface gráfica, mas a parte que tenho dúvidas é a do acesso a banco de dados.

[quote=AbelBueno]Você não falou que tinha feito as alterações que eu sugeri???

Tente isso:

    public static int[] pegaDadosIniciais() throws SQLException{

        int[] resposta = {0,0,0,0,0,0,0,0,0,0,0,0};

        PreparedStatement objSQLTotProd = objCon.prepareStatement("SELECT COUNT(*) AS TOTPROD FROM TABPRODUTOS");
        ResultSet objRespTotProd = objSQLTotProd.executeQuery();
        if (objRespTotProd.next()){
            resposta[0] = objRespTotProd.getInt("TOTPROD");
        }

        PreparedStatement objSQLTotCli = objCon.prepareStatement("SELECT COUNT(*) AS TOTCLI FROM CLIENTES");
        ResultSet objRespTotCli = objSQLTotCli.executeQuery();
        if (objRespTotCli.next()){
            resposta[1] = objRespTotCli.getInt("TOTCLI");
        }
       return resposta;
    }

[/quote]

Ahhhh. Tinha feito outra coisa mesmo. Tinha entendido diferente.

Agora deu certinho. Muito obrigado. :smiley: