Quando fechar uma conexao com BD?

aki vai uma pergunta bastante ignorante:
Pq eu devo fechar uma conexao?

eu fiz alguns testes e praticamente consequi roda um programinha inteiro sempre com uma unica conexao aberta, eu criei ela quando a primera janela abre e deixei pra fechar quando o aplicativo fosse encerrado. Funcionou normalmente!

Fiz esse teste em um aplicativo Cliente-Servidor com 5 clientes!

Se você utilizar algum programa que faça profiling do banco vai ver que a conexão faz uma coisa de cada vez, por isso se for ter muito acesso simultâneo é melhor utilizar mais de uma conexão, e aí tem que ter um certo controle para não sobrecarregar o banco. Normalmente o que é feito é utilizar um pool de conexões ao invés de realmente ficar abrindo e fechando as conexões.

daniel…
aqui na empresa onde trabalho o pessoal esta tendo problemas exatamente com isso…
Ja imaginou 50 classes abrindo uma conexao cada uma…eh complicado neh? ja imaginou o tanto de cursores aberto no BD? ja imaginou sua aplicação dando pau de BD tb neh? :smiley:

Eh complicado com certeza!!

ate mais…

Me digam algo veja se meu pensamento está certo…eu poderia criar uma classe Conexao a qual nao importa quantas vezes eu a isntancie, ela só cria um objeto… eu sei q dá pra fazer isso em java só nao sei se deve ser usado no caso de conexao com DB.

Deve ??? ou Pode ???

No caso eu determino quantas vezes a classe pode ser instanciada…exemplo eu permito 3 se ela passar disso, ela aponta para o mesmo objeto…

Devo ??? ou Pode ??? :?

eu acho q deve-se criar apenas uma conexao com o banco e usa-la sempre…
assim vc rpeserva o seu banco de ter varias conexoes por usuario do sistema…

falow

Ter um singleton (classe com só uma instância) é uma boa técnica para aplicações com poucos usuários, mas acaba não sendo muito escalável.
Connection Pool é melhor e existem projetos open source para implementá-la.

Entã oq eu fiz não tá muito errado?
Eu tenho poucos usuarios conectados, posso manter uma conexão para cada e fazer tudo com ela, desde que não faça operações simultaneas!!

Em ambiente de testes, nao fechar as conexoes nao vai fazer diferenca na maior parte dos casos, pois voce quase nunca usa o sistema tao intensamente a ponto de ficar sem conexao.
O problema acontece quando ha muita gente ao mesmo tempo, ou por um lonngo periodo, utilizando os recursos.

Se vc nao usar um connection pool, vai perder performance tendo que abrir conexoes o tempo todo, e nao fechando, a probabilidade de ficar com muitos objetos desnecessarios em memoria eh relativamente grande.
Se voce usar um connection pool e nao devolver as conexoes, vai chegar uma hora em que o pool estara vazio, e ai pode acontecer os mais diversos erros ( por nao ter uma conexao, enquanto o teu programa espera que tenha ).

Nos sistemas que implemento, tento fazer de uma forma com que somente uma unica conexao seja usada por requisicao, passando a referencia para quem precisar. Nunca deixo a responsabilidaed de pegar uma conexao do pool e devolver a mesma para as classes de negocios, pois eh mto propicio a erros. O que faco eh delegar ao controlador a tarefa de pegar uma conexao e fechar ela.

Rafael

como o Rafael disse, no caso de ser ambiente de teste, tudo bem…mas quando se coloca um sistema no ar com esse problema dai fica complicado…como dissemos, procure usar somente uma conexao…para que conexoes nao fiquem perdidas, cursores abertos e o caos se instalando no seu sistema!! :lol: 8)

a ideia de pool de conexão que a Bani passou aqui no post eu achei muito interessante…

Bani, vc poderia falar mais a respeito disso??
tem como dar um exemplo?? :smiley:

Obrigado!

ate mais…

As implementações de connection pool variam caso a caso, e normalmente você pode parametrizar quantas conexões deixar abertas inicialmente e quando criar novas conexões.
Eu costumava usar o do WebSphere mesmo, mas se você quiser dar uma olhada em um free pode usar o do Jakarta: http://jakarta.apache.org/commons/dbcp/

[quote]Me digam algo veja se meu pensamento está certo…eu poderia criar uma classe Conexao a qual nao importa quantas vezes eu a isntancie, ela só cria um objeto… eu sei q dá pra fazer isso em java só nao sei se deve ser usado no caso de conexao com DB.

Deve ??? ou Pode ???

No caso eu determino quantas vezes a classe pode ser instanciada…exemplo eu permito 3 se ela passar disso, ela aponta para o mesmo objeto…

Devo ??? ou Pode ??? (kartler)[/quote]

Poder, pode. Dever, não deve. Os motivos são os seguintes:

  • como já disseram, escala muito mal;
  • classes Singleton (nome dado às classes com a propriedade que você descreveu) precisam ter todos seus métodos sincronizados para evitar race conditions :frowning: ;
  • lendo um artigo (este aqui: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html) percebi que Singleton traz mais problemas do que resolve (percebi também que nem sincronização - dita acima - basta para se evitar race conditions);

Tem outros motivos, mas é muito blablabla. Como disseram, use um Connection Pool, já que é bem simples de ser usado e traz vários benefícios (escalabilidade, performance, recursos gerenciados mais eficientemente, elegância…). Se você não quiser usar um projeto O-S (talvez por motivos religiosos, sei lá), faça a sua própria implementação, pois é bem simples (e é um bom exercício também).

Bom, é isso. Fui muito acaciano para um post só.

Hmmm…

Race conditions são criadas exatamente pela sincronização, um código não sincronizado não tem corrida.

A corrida acontece pq quando duas Threads tentam pegar um lock (no caso mais simples, entrar num bloco synchronized), a que pegar primeiro continua, a outra tem que esperar até o lock ser liberado.

Todos os pools que vc inventar no mundo vão ser sincronizados, e por isso vão ter corridas. A idéia de compartilhar a conexão pra várias Threads não é ruim, pq as regiões críticas são muito pequenas. Mas vc precisa fazer um fine tuning…

Vamos considerar uma aplicação em Servlets cujo cenário típico é o seguinte:

  • O servlet pega a conexão, faz várias queries pequenas (pra montar uma página de cadastro, por exemplo) e devolve a conexão.
  • O servlet pega a conexão, faz zero ou uma alterações no banco, e a devolve.

Nesse caso, um pool de tamanho razoável tem uma chance grande de ter conexões livres. Daí não vale a pena compartilhar a mesma conexão com vários “clientes”.

Um outro cenário é uma aplicação RMI, onde tipicamente um “cliente” segura uma conexão bastante tempo e faz operações pequenas e a intervalos irregulares. A chance de vc ter conexões livres no pool diminui, mas em compensação o uso efetivo de cada conexão é baixo. Daí vale a pena compartilhar uma conexão com vários “clientes”.

“clientes” entre aspas significam um objeto que mantém uma conexão aberta em uma Thread.

O que vcs acham, viajei?

[]s

O jdbc 3.0 (ou eh o 2.0) implementa a decadas o DataSource q PODE ser implementado pelo driver e atraves da naming api voce encontra uma connection pool TRANSPARENTE… isto eh: ela sera um objeto Connection qualquer que ao ser .close() e =null ele volta pra connection pool do driver… quando alguem requisitar a mesma conexao ele vai retornar uma do pool…
A implementacao, uma vez que eh do driver, varia muito sobre a sincronizacao e qq outra coisa, pode ser tanto nativa (ver o sprinter pra microsoft sql server) como nao… feito em java… isto eh, todo aquele bla bla bla sobre os 4 tipos de drivers jdbc podem implementar isso…

Sinceramente, esse eh o melhor tipo de pool pois eh totalmente transparente e pode ser ligado desligado em um arquivo de configuracao…

Outra opcao eh implementar sua propria ou usar a da Apacjhe, por exemplo… eu estava pensando em fazer um tutorialzinho sobre Pool e Cache aqui no guj… nao sei se o pessoal tem interesse mas eh uma coisa que todo projeto que faco utiliza entao ja fiz milhares de opcoes possiveis…

Como o tiago falou, nao da pra escapar de pools sem sincronizacao, mas nao entendo pq a sincronizacao pra um singleton pode ser tao ruim assim… pois entao qual seria os problemas que podem ocorrer com a classe DateFormat que utiliza parcialmente o singleton (por exemplo)?

Continuando ja que a empolgacao eh muita, nao usando uma connection pool vc cai no problema que todos falaram… que se resume a abrir 100 cursores no banco de dados e ele simplesmente recusar novos clientes… com certeza vc NAO quer isso… mas nao eh isso que a connection pool vai resolver se a sua aplicacao eh distribuida pois vc tera 10 conexoes em 10 clientes ja totalizaram 100 cursores… ai a unica saida eh criar connection pools com time outs, que fecham as connections apos certo tempo nao utilizada… opcoes e mais opcoes…

[]s

Guilherme

[quote=Bani]As implementações de connection pool variam caso a caso, e normalmente você pode parametrizar quantas conexões deixar abertas inicialmente e quando criar novas conexões.
Eu costumava usar o do WebSphere mesmo, mas se você quiser dar uma olhada em um free pode usar o do Jakarta: http://jakarta.apache.org/commons/dbcp/[/quote]

Tudo bem Bani,

Estou com uma aplicação que roda no WebSphere que está tendo sérios problemas com conexões e como vc trabalha com WebSphere, gostaria de saber se poderia me dar uma ajuda!
O meu objeto que pega a conexão via DataSource é um Singloton, será que o problema pode estar ai???
Essa aplicação utiliza mais de 100 usuários simultâneos, como vc aconcelha que eu controle essas conexões???

Atenciosamente,
Éber.

Só para falar um pouquinho…

Normalmente quando a gente vê um fonte de implementação de java.sql.DataSource já se vê que o padrão desejado para o uso de uma conexão obtida via DataSource é:

  • pegar a conexão (só pega a conexão do pool, pode até ser que crie uma conexão se o pool ainda não estiver totalmente inicializado…)
  • usá-la; e
  • fechá-la logo em seguida (close só devolve a conexão ao pool; normalmente nem efetua o fechamento “físico” da conexão…).

Ou seja, tanto pegar uma conexão quando fechar são operações muito rápidas (não envolvem chamada ao banco) e podem ser repetidas quase que a cada comando SQL.

Pode ser que na tentativa de evitar chamar “close”, deixando a conexão o máximo de tempo aberta, acabemos negando os benefícios de se usar java.sql.DataSource.