Como se fecha uma conexão usando JDBC?

Olá, estou fazendo um programa que usa conexão com o Postgres, fiz um cadastro de clientes e pra teste inclui 10.000 egistros pra ver como se comportava.
Fiz uma janelinha tambem pra mostrar as informações dos clientes, aonde tenho uma tabela que mostra todos os clientes cadastrados, e na tabela fiz um evento que cada vez que o usuario pressionasse tecla pra cima ou pra baixo pra selecionar o proximo registro ou o anterior, ele carregasse umas informações adicionais em baixo da tabela. ok até ai tudo bem, porem quando o usuario segura a tecla pra baixo continuamente, obrigando o programa a ir descendo rapidamente na tabela de clientes e fazendo muitos selects pra consultar esses dados adicionais, ocorre que em determinado ponto o postgres da um erro dizendo que há muitos usuários conectados(mesmo assim dando OK nesse erro ele continua funcionando normalmente).
Pelo que entendi cada vez que se faz um select ele não fecha a conexão, ficando com muitas conexões abertas na memória, mas como posso fazer pra fechar essas conexões? sendo que estou usando JDBC puro, sem framework, eu armazeno os resultados da consulta em um ResultSet.

a conexao pode ficar aberta, o correto eh fechar o statement; use seu_statement.close();
recomendo fechar a conexao somente quando encerrar a aplicacao; use sua_conexao.close();

posta ai teu codigo parceiro

Connection con …
ResultSet rs …

//feche na ordem que abriu rs.close(); con.close();

etc…

preferencialmente utilize dentro do finally, exemplo:

try { ... catch(Exception e){ ... } finally { ... }

Segue meu código, tentei fechar o statement mas continuou dando o mesmo erro:

[code]/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */

package Conexoes;
import java.sql.*;
import java.util.ArrayList;
import javax.swing.JOptionPane;
/**
*

  • @author adm
    */
    public class ObterDadosConsultaOrdemAlfabet {

    public ArrayList obterDados(String codCliente, String caminhoDoBanco) {
    codCliente+="";
    String database = caminhoDoBanco; // jdbc:postgresql://localhost/locadoras eh o q deve ta dentro do arquivo
    String usuario = “postgres”;
    String senha = “masterkey”;
    String driverName=“org.postgresql.Driver”;
    Connection conexao;
    Statement consulta;
    ResultSet resultado;
    ArrayList dados=new ArrayList();
    try{
    Class.forName(driverName);
    conexao = DriverManager.getConnection(database,usuario,senha);
    consulta = conexao.createStatement();
    resultado = consulta.executeQuery(“select c.ende,c.bairro,i.cidade,i.estado from cadastro_clientes c”+
    " left join cidades i on i.codcidade=c.codcid where c.codcli="+codCliente);
    while(resultado.next()){
    String ende=resultado.getString(“ende”); if(ende==null){ende=" “;}
    dados.add(ende);
    String bairro=resultado.getString(“bairro”); if(bairro==null){bairro=” “;}
    dados.add(bairro);
    String cidade=resultado.getString(“cidade”); if(cidade==null){cidade=” “;}
    dados.add(cidade);
    String estado=resultado.getString(“estado”); if(estado==null){estado=” ";}
    dados.add(estado);
    }

        consulta.close();
    }catch(Exception e){JOptionPane.showMessageDialog(null, e.getMessage());}
    return dados;
    

    }

}
[/code]

feche o resultado, consulta, conexao respectivamente…

com .close() no final

O problema continua prq vc abre a conexao em todos os selects;

seu codigo precisa de algumas correções.

1º use um fabrica de conexoes, procure aqui no forum que deve ter um monte de coisa a respeito
2º faça com que sua conexão seja um singleton e a mantenha aberta durante o uso da aplicacao, eh menos custoso do que abrir e fechar
3º nunca use statement troque por preparedStatement eh melhor e mais seguro

obrigado, por enquanto estou fechando a conexão em cada vez que passa pelo select, isso ja resolveu meu problema, mas vou fazer como o amigo ai em cima falou, usando fabrica de conexões, ja percebi que é 1000 x melhor do qe o jeito que estou fazendo.
Esse fórum é demais hehe…

[quote=mauricioadl]O problema continua prq vc abre a conexao em todos os selects;

seu codigo precisa de algumas correções.

1º use um fabrica de conexoes, procure aqui no forum que deve ter um monte de coisa a respeito
2º faça com que sua conexão seja um singleton e a mantenha aberta durante o uso da aplicacao, eh menos custoso do que abrir e fechar
3º nunca use statement troque por preparedStatement eh melhor e mais seguro
[/quote]

O uso de singletons deve ser feito somente com supervisão de um adulto. Evite-os a todo custo, a grande maioria esmagadora da utilização de Singletons é desnecessária tanto que esse se tornou um anti-padrão documentado (embora esteja como um padrão de projetos no livro do GoF).

Não mantenha uma conexão aberta durante a vida toda da aplicação, no final das contas essa será encerrada pelo próprio SGBD e você morrerá com uma exception ao tentar usa-la.
Isso sem contar que estará guardando um recurso desnecessariamente, aumento o custo computacional da aplicação.

O correto é abrir uma conexão por transação necessária e encerra-la tão logo a transação finalize.
Seria de bom tom (e mais inteligente) o uso de um pool de conexões, deixando que esse gerencie as conexões, cabendo a você pedi-las e devolve-las no inicio e fim das transações respectivamente, ficando transparente a quem a usa detalhes como usuário e senha do banco (algo semelhante a factory de conexões).

Existem dezenas de pools por ai, de uma olhada no C3PO e Nano Pool, embora existam outras alternativas.

[quote=Tchello][quote=mauricioadl]O problema continua prq vc abre a conexao em todos os selects;

seu codigo precisa de algumas correções.

1º use um fabrica de conexoes, procure aqui no forum que deve ter um monte de coisa a respeito
2º faça com que sua conexão seja um singleton e a mantenha aberta durante o uso da aplicacao, eh menos custoso do que abrir e fechar
3º nunca use statement troque por preparedStatement eh melhor e mais seguro
[/quote]

O uso de singletons deve ser feito somente com supervisão de um adulto. Evite-os a todo custo, a grande maioria esmagadora da utilização de Singletons é desnecessária tanto que esse se tornou um anti-padrão documentado (embora esteja como um padrão de projetos no livro do GoF).

Não mantenha uma conexão aberta durante a vida toda da aplicação, no final das contas essa será encerrada pelo próprio SGBD e você morrerá com uma exception ao tentar usa-la.
Isso sem contar que estará guardando um recurso desnecessariamente, aumento o custo computacional da aplicação.

O correto é abrir uma conexão por transação necessária e encerra-la tão logo a transação finalize.
Seria de bom tom (e mais inteligente) o uso de um pool de conexões, deixando que esse gerencie as conexões, cabendo a você pedi-las e devolve-las no inicio e fim das transações respectivamente, ficando transparente a quem a usa detalhes como usuário e senha do banco (algo semelhante a factory de conexões).

Existem dezenas de pools por ai, de uma olhada no C3PO e Nano Pool, embora existam outras alternativas.[/quote]

concordo com vc em algumas coisas e outras nao Eh muito comum ver muita gente falando para fechar as conexoes ao terminar de usar, fazer isso numa base oracle vai ter um sistema mais lendo que o windows 98 rodando num 386. Manter a conexao aberta eh muito leve comparado ao abrir e fechar principalemente em um sistema q manipula dados constantemente.
isso eh minha opniao eh claro!

Faço minhas as palavras do Tchello.

Manter uma conexão aberta é fria por vários motivos:

  1. Você fica ocupando o recurso no banco, sem usa-lo. Isso limita drasticamente o número de usuários simultâneos em sua aplicação;
  2. Conexões simultâneas podem ser necessárias para processamento concorrente;
  3. A solução que o Tchello apontou gerencia automaticamente a abertura/fechamento das conexões, evitando o problema de performance que você mencionou, e o erro que conexão fechada que o Tchello mencionou;
  4. É uma boa prática de programação manter os recursos fechados, no finally, como recomenda o próprio criador da linguagem java: http://www.ibm.com/developerworks/java/library/j-jtp03216/index.html
  5. É ridiculamente fácil usar o C3P0 ou o DBCP.
  6. Frameworks de persistência, como o Hibernate e Spring também trabalham com conexões fechadas.

Mauricio, informe-se sobre os pools de conexão e você vai ver que rodam bem até mesmo no Oracle, com a conexão devidamente fechada.

[quote=mauricioadl]
concordo com vc em algumas coisas e outras nao Eh muito comum ver muita gente falando para fechar as conexoes ao terminar de usar, fazer isso numa base oracle vai ter um sistema mais lendo que o windows 98 rodando num 386. Manter a conexao aberta eh muito leve comparado ao abrir e fechar principalemente em um sistema q manipula dados constantemente.
isso eh minha opniao eh claro![/quote]

O que quero dizer vai além da opinião pessoal, mas vai de bom senso seguindo boas práticas que só a experiência te mostra.
Se em uma entrevista alguém me disser essa estratégia de manter uma conexão aberta com certeza isso pesará muito para que eu não contrate o sujeito.

E outra, sugiro veementemente que estude a respeito de pool de conexões.

Vini, eh impossivel discutir algo com vc, prq vc eh um dos maiores javeiros do brasil e tem meu eterno respeito.
se eu nunca te agradeci, obrigado! vc me ajudou muito varias e varias vezes.

Trabalhar com as regras de negocio dentro do oracle usando pl sql fica impossivel usar frameworks, pois quase 90% das chamadas sao procedures.
Todas as chamadas simultaneas caem na mesma servlet, entao uma unica conexao eh necessaria, ja que o oracle da um lock nas outras qndo vai fazer a tarefa.
Tentamos por muito tempo fazer varias tecnicas para fechar, pool, fabrica, etc mas todas perdiam desempenho.
o oracle demora 5s exatos para abrir a conexao, imagine um ERP fazendo de 1000 a 2000 chamadas por hora, fica tenso o negocio
Como vivenciei isso por bastante tempo, acredito veementemente que mante-la aberte eh uma boa solução, pelo menos no meu caso.
eh claro que se vc tem um blog q usa o banco so pra gravar o e-mail vc nao vai fazer isso e nem usar um banco do tamanho do oracle, bom senso eh tudo.

[]'s

[quote=Tchello][quote=mauricioadl]
concordo com vc em algumas coisas e outras nao Eh muito comum ver muita gente falando para fechar as conexoes ao terminar de usar, fazer isso numa base oracle vai ter um sistema mais lendo que o windows 98 rodando num 386. Manter a conexao aberta eh muito leve comparado ao abrir e fechar principalemente em um sistema q manipula dados constantemente.
isso eh minha opniao eh claro![/quote]

O que quero dizer vai além da opinião pessoal, mas vai de bom senso seguindo boas práticas que só a experiência te mostra.
Se em uma entrevista alguém me disser essa estratégia de manter uma conexão aberta com certeza isso pesará muito para que eu não contrate o sujeito.

E outra, sugiro veementemente que estude a respeito de pool de conexões.[/quote]

se vc comecar a usar oracle vai descobrir q ele implementa um pool automaticamente.

vc pergunta sobre pool na entrevista? eh serio?

[quote=mauricioadl][quote=Tchello][quote=mauricioadl]
concordo com vc em algumas coisas e outras nao Eh muito comum ver muita gente falando para fechar as conexoes ao terminar de usar, fazer isso numa base oracle vai ter um sistema mais lendo que o windows 98 rodando num 386. Manter a conexao aberta eh muito leve comparado ao abrir e fechar principalemente em um sistema q manipula dados constantemente.
isso eh minha opniao eh claro![/quote]

O que quero dizer vai além da opinião pessoal, mas vai de bom senso seguindo boas práticas que só a experiência te mostra.
Se em uma entrevista alguém me disser essa estratégia de manter uma conexão aberta com certeza isso pesará muito para que eu não contrate o sujeito.

E outra, sugiro veementemente que estude a respeito de pool de conexões.[/quote]

se vc comecar a usar oracle vai descobrir q ele implementa um pool automaticamente.

vc pergunta sobre pool na entrevista? eh serio?[/quote]

First of all, 2000 mil requisições por hora não são nada. Reduza isso pelo menos por minuto, quiçá menos.

Que diferença faz qual SGBD se usa quando o que discutimos é um pool?
Se eu começar a usar Oracle? Isso só pode ter sido piada.

Calma gente, também não é para tanto.

Aqui na Positivo usamos o SQL em uma situação muito parecida com a sua: boa parte da lógica de negócio está em SPs, no banco.

Atualmente essa é uma prática desatualizada, principalmente no caso dos sistemas webs. Os bancos de dados tem um problema sério, que é ter pouca escalabilidade horizontal. Por isso, a tendência é mover a lógica para os servidores de aplicação, mesmo que eles tenham uma performance menor à princípio. É barato e fácil adicionar um servidor à infra-estrutura.

No caso de sistemas Desktop, eu ainda prefiro usar o Pool, mas se você tomar cuidado, não creio que nada de castastrófico irá ocorrer. Você pode facilmente verificar se a conexão está viva antes de retorna-la. Só cuidado com gargalos na parte de multi-threading, o que não é um problema no seu SGDB específico (o Oracle gerencia isso pelos Statements, não pelas conexões).

[quote=Tchello][quote=mauricioadl]O problema continua prq vc abre a conexao em todos os selects;

seu codigo precisa de algumas correções.

1º use um fabrica de conexoes, procure aqui no forum que deve ter um monte de coisa a respeito
2º faça com que sua conexão seja um singleton e a mantenha aberta durante o uso da aplicacao, eh menos custoso do que abrir e fechar
3º nunca use statement troque por preparedStatement eh melhor e mais seguro
[/quote]

O uso de singletons deve ser feito somente com supervisão de um adulto. Evite-os a todo custo, a grande maioria esmagadora da utilização de Singletons é desnecessária tanto que esse se tornou um anti-padrão documentado (embora esteja como um padrão de projetos no livro do GoF).

Não mantenha uma conexão aberta durante a vida toda da aplicação, no final das contas essa será encerrada pelo próprio SGBD e você morrerá com uma exception ao tentar usa-la.
Isso sem contar que estará guardando um recurso desnecessariamente, aumento o custo computacional da aplicação.

O correto é abrir uma conexão por transação necessária e encerra-la tão logo a transação finalize.
Seria de bom tom (e mais inteligente) o uso de um pool de conexões, deixando que esse gerencie as conexões, cabendo a você pedi-las e devolve-las no inicio e fim das transações respectivamente, ficando transparente a quem a usa detalhes como usuário e senha do banco (algo semelhante a factory de conexões).

Existem dezenas de pools por ai, de uma olhada no C3PO e Nano Pool, embora existam outras alternativas.[/quote]

Neste caso eu discordo por causa de uma questão de contexto:

[quote=mateusviccari]Olá, estou fazendo um programa que usa conexão com o Postgres, fiz um cadastro de clientes e pra teste inclui 10.000 egistros pra ver como se comportava.
Fiz uma janelinha tambem pra mostrar as informações dos clientes, aonde tenho uma tabela que mostra todos os clientes cadastrados, e na tabela fiz um evento que cada vez que o usuario pressionasse tecla pra cima ou pra baixo pra selecionar o proximo registro ou o anterior, ele carregasse umas informações adicionais em baixo da tabela. ok até ai tudo bem, porem quando o usuario segura a tecla pra baixo continuamente, obrigando o programa a ir descendo rapidamente na tabela de clientes e fazendo muitos selects pra consultar esses dados adicionais, ocorre que em determinado ponto o postgres da um erro dizendo que há muitos usuários conectados(mesmo assim dando OK nesse erro ele continua funcionando normalmente).
Pelo que entendi cada vez que se faz um select ele não fecha a conexão, ficando com muitas conexões abertas na memória, mas como posso fazer pra fechar essas conexões? sendo que estou usando JDBC puro, sem framework, eu armazeno os resultados da consulta em um ResultSet.[/quote]

A questão aqui é que está abrindo muitas requisições e fechando-as num período curto de tempo… eu acho válido um pool de conexões quando a aplicação é acessada por vários usuários fazendo várias coisas diferentes, mas veja só esse caso, é uma aplicação desktop, só um usuário vai estar usando. para que mais de uma conexão? Para que duas conexões ao mesmo tempo consultando duas linhas provavelmente seguidas da mesma tabela? Nesse caso eu sou a favor de manter uma conexão sim e reaproveita-la, mas concordo que singleton deve ser usado com cuidado, só onde seja ruim ter mais de um do mesmo recurso. Até acho viável usar algum framework como c3p0 para fechar uma conexão quando estiver inativo e abrir quando for usar mas não vejo onde algo assim precisa de mais de uma conexão. Usar mas de uma conexão ai não deveria ser necessário e demonstra que tem algum outro problema, só acho que você tem que fazer o máximo para fechar estas conexões assim que der se tiver muito usuário acessando ao mesmo tempo (centenas) essa base, o que é incomum em aplicação desktop mas se for para ficar fechar e reabrir logo em seguida ai ainda não vale a pema, se for usar duas conexões ao mesmo tempo para um só usuário ai que não vale a pena mesmo (isso seria meio desastroso com vários usuários ao mesmo tempo, pioraria ainda mais o problema).

Editando, o único caso onde vejo a necessidade de duas conexões para um único usuário é se ele estiver fazendo duas coisas ao mesmo tempo onde ambas precisam de uma conexão separada, mas não é bem esse o caso, seria por exemplo se o usuário puder deixar o sistema fazendo algo demorado que use o banco e possa fazer outras coisas enquanto o sistema faz isso em segundo plano por exemplo. Nesse caso procure usar um pool com a quantidade minima de requisições em um e verifique se não está indo para duas conexões sendo usadas quando não deveria.

Mateus outra dica que eu dou é que quando o usuário clicar na seta para baixo e você precisar pegar a próxima linha, não pegue uma linha só, pegue as próximas 50, 100, sei la, assim nas outras 49 você não precisa voltar la no banco. Acredito que as IDEs como o toad por exemplo fazem isso, inclusive se bem me lembro quando o usava, se você fizer isso bastante numa mesma consulta essa quantidade de linhas buscadas por vêz aumentava. Como o vini disse, feche seus recursos no finally.

Cláro que isso é só minha opinião (alias quando eu reparo que estou discordando do que o vinigodoy disse eu penso se não estou errado umas vezes… :slight_smile: ).

Epa, calma ae.
Eu disse uma conexão por transação, ou seja, quando precisar executar algo no banco abre uma conexão, usa tudo que precisa e quando não precisar mais fecha-la.
Não uma conexão por consulta. As coisas mudam bastante com isso.

[quote=Tchello] Epa, calma ae.
Eu disse uma conexão por transação, ou seja, quando precisar executar algo no banco abre uma conexão, usa tudo que precisa e quando não precisar mais fecha-la.
Não uma conexão por consulta. As coisas mudam bastante com isso.[/quote]

isso não se aplica no caso em questão (se eu intendi direito o que você disse, é claro), cada consulta é feita em separado da outra e inclusive elas nem precisam de uma transação aberta, nesse caso não da para abrir a conexão, fazer o que tiver que fazer e depois fechar. Se for ver bem se essa aplicação tiver um pool de 5, 10 conexões (sei la) e o usuário deixar a seta para baixo pressionada ao invés de abrir várias conexões iria abrir só 5 nesse caso que ele tem (ainda não está bom). Ainda acho que multiplas conexões numa aplicação desktop só podem ser usadas em processamento paralelo (e não é esse o caso). Nesse caso, caso a mesma tela precisa de outra coenxão para fazer a mesma coisa, provavelmente deveria haver um refactor para aproveitar a mesma para fazer isso na mesma consulta, no pior dos casos aguardar a conexão liberar e usa-la (eu vejo multiplos usuários tendo multiplas conexões algo que deve fortemente ser evitado, isso sim abriria muitos recursos na base, por isso nesse caso acho que o pool exige mais cuidado que o singleton, o que é beeeem irônico, cada caso é um caso).

concordo com o maior_abandonado:
1- o contexo em questao facilitaria uma unica conexao, e fecha-la apenas qndo nao houver atividade.
2 - se minha opniao confronta com a do vini, repenso meus conceitos.

concodo com o vini:
1 - concordo q eh ma pratica manter a regra dentro do banco, mas se for um ERP, por exemplo, o ganho eh esmagador devido a qntidade de acesso. e tbm eh mais facil achar profissionais de PL/SQL q eh o caso em q vivo do q profissionais de Java. (Isso onde moro, nao sei onde vcs moram)
2 - o oracle gerencia as conexoes pelo statement, criando um pool proprio para suas requisiçoes, acho que o sql server tbm faz isso
3 - verificar se a conexao esta ativa antes de usar, nao gera problema. um sigleton cai bem nisso.