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.
AlexandreGama
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!
E
ElvisCamilo
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.
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:
publicstaticString[]pegaDadosIniciais()throwsSQLException{PreparedStatementobjSQLTotProd=objCon.prepareStatement("SELECT COUNT(*) AS TOTPROD FROM TABPRODUTOS");ResultSetobjRespTotProd=objSQLTotProd.executeQuery();PreparedStatementobjSQLTotCli=objCon.prepareStatement("SELECT COUNT(*) AS TOTCLI FROM CLIENTES");ResultSetobjRespTotCli=objSQLTotCli.executeQuery();String[]objResposta[];//Faz CastobjResposta[0]=""+objRespTotProd.getInt("TOTPROD");objResposta[1]=""+objRespTotCli.getInt("TOTCLI");//Obteu os dados com sucesso se não retorna erroif(objRespTotProd.next()){returnobjResposta;}else{thrownewSQLException("Falha ao obter estatísticas iniciais.");}}
A idéia é mais ou menos essa. Só que a função retorna um SQLException falando do "Result set already Closed.", ou algo assim.
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){
returnobjResposta;
}else{
thrownewSQLException("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
E
ElvisCamilo
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){
returnobjResposta;
}else{
thrownewSQLException("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
Estranha? Como assim?
E
ElvisCamilo
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){
returnobjResposta;
}else{
thrownewSQLException("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
Ainda deu o mesmo erro. Eu acho que o problema tá na utilização dos métodos do SQL.
A
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)
E
ElvisCamilo
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)
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.
A
AbelBueno
Você tentou a minha primeira sugestão?
E
ElvisCamilo
Você tentou a minha primeira sugestão?
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?
A
AbelBueno
Como ficou o código depois destas alterações?
E
ElvisCamilo
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.
A
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;
}
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.
E
ElvisCamilo
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. ;)
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.
E
ElvisCamilo
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;
}
Ahhhh. Tinha feito outra coisa mesmo. Tinha entendido diferente.