Mantendo Conexão do Banco aberta para outras classes

16 respostas
D

Pessoal, estou desenvolvendo uma aplicação para ganhar conhecimento em java, mas ainda tenho muitas dúvidas.

O Problema é o seguinte: Criei uma classe para fazer a connexão em um banco de dados e verificar a existencia de um usuário para logar no programa.
Mas para cada item do meu menu eu estou chamando uma outra classe que estrende JFrame e quero continuar usando a mesma conexão aberta na tela inicial do sistema.

Como faço isso?

16 Respostas

Rafael_Nunes

Passe o objeto Connection para estas classes.

marcioa1

Considere o uso de um pool de conexões. O DBCP, do projeto Jakarta, é uma opção simples e eficiente.

http://jakarta.apache.org/commons/dbcp/

Márcio

paulinhohd

Faça a classe Pool de Conexão e instancie objetos nas outras classes.

Lembrando que é muito importante fechar a conexão de seu banco depois de encerrado sua consulta, ou inserção etc.

Valeu! 8)

_fs

E não “deixe a conexão aberta”. Nunca. Abra, use e feche o mais rápido possível. Sempre.

D

Galera, valeu pelas dicas eu realmente estava deixando a conexão aberta, e vou pensar no caso do pool de conexões.

Então já que criei uma classe de connexão, eu poderia utilizar essa classe para fazer minhas consultas atravez de métodos ou não sería uma forma muito boa?

paulinhohd

Se quiser acessar o bd dentro de outras classes sim! 8)

Thiago_Senna

Que tal usar a classes ThreadLocal ao invés de ficar passando a conexão por parâmetro? :wink:

marcioa1

Thiago,

Não entendi a história do ThreadLocal. No meu projeto (Swing com poucos usuários ) eu uso uma classe de conexão (implementando um singleton) e sempre que preciso de uma conexão, eu uso um método getconnection() que retorna a variável de conexão estática.

private static Connection conn = null;
public static Connection getConnection(){
		if (conn==null){
			try{
				Class.forName(nomeDoDriver);
				conn = DriverManager.getConnection(url,username,password);
			} catch ...
			
		} 
		try {
			if (conn.isClosed()){
				try{
					Class.forName(nomeDoDriver);
					conn = DriverManager.getConnection(url,username,password);
				} catch  ...
		}
		return conn;
	}

Isto pode ser melhorado ?

Obrigado,

Márcio

Rafael_Nunes

Se você não está usando um pool como o dbcp, esta é uma alternativa.

Uma 'metodologia' que eu costumava usar era criar uma classe com a conexão e as informações do Statement, ResultSet e afins.

Por exemplo:
class BancoDados{
  protected ResultSet rs;
  protected Statement stmt;
  protected Connection con;
  
  public Connection getConnection(){
  ...//implementação que pega a conexão
   }
E as minhas classes DAO eu extendia de BancoDados. Mas o problema é que você precisa passar o objeto conexão entre as classes. É, acho que meu comentário não acrescentou muita coisa.
smota

eheheh não é bem assim. Esse é o negócio do pool de conexões, ele abre, e deixa aberta e fica fornecendo essas conexões conforme são pedidas, ao devolver ao pool ele nem sempre fecha a conexão (na verdade, em geral, só fecha se há mais conexões abertas do que o configurado para ele manter).

Claro que isso tudo depende da sua aplicação e da sua licença do banco ehehehe.

NUNCA deixe cursores abertos :lol: , abra, use e feche.

marcioa1

Da forma que desenvolvo em Swing, cada usuário abre uma JVM na qual reside a classe de conexão. Sendo assim não vejo razão para criar um pool. Pool para um único usuário ?

Estou acreditando que o Spring resolva estes casos de uma forma mais elegante, criando (em um servidor) um pool de conexões e, cada cliente, com sua JVM, obtendo a conexâo deste pool.

Estou falando besteira ?

Márcio

paulinhohd

marcioa1:
Da forma que desenvolvo em Swing, cada usuário abre uma JVM na qual reside a classe de conexão. Sendo assim não vejo razão para criar um pool. Pool para um único usuário ?

Estou acreditando que o Spring resolva estes casos de uma forma mais elegante, criando (em um servidor) um pool de conexões e, cada cliente, com sua JVM, obtendo a conexâo deste pool.

Estou falando besteira ?

Márcio

A intenção não seria fazer com que cada usuário abrisse a classe conexão, e sim criar um pool único onde cada usuário o acessaria…creio que seja isso, agora não sei se foi eu que te falei besteira rs?

Mas pela dúvida acho que é isso.

Quanto a Spring, nunc ouvi falar, se alguém quiser compartilhar seus conhecimentos rs?

Valeu! 8)

marcioa1

É isto mesmo. Qual seria a solução ? RMI ? Minha aplicação é Swing!

Márcio

_fs

Smota, que tal comentar todas as linhas que tem conn.close() nas suas aplicações? hehe pra devolver pro pool tem que fazer conn.close(). Se não estiver usando pool, tem que fazer conn.close(). Se estiver tomando um chazinho da tarde, tem que fazer conn.close(). Não tem como fugir cara :smiley:

paulinhohd

Bom minha aplicação é applet, porém creio que não influencia muito, mas eu criei o pool de conexão, e consigo acessar de qualquer local do programa, agora não sei se é isso que vc pretende fazer…ou vc está fazendo uma aplicação cliente-servidor? Pois daí poderia deixar o pool de conexão só no servidor…

Valeu! 8)

Thiago_Senna
marcioa1:
Thiago,

Não entendi a história do ThreadLocal. No meu projeto (Swing com poucos usuários ) eu uso uma classe de conexão (implementando um singleton) e sempre que preciso de uma conexão, eu uso um método getconnection() que retorna a variável de conexão estática.

private static Connection conn = null;
public static Connection getConnection(){
		if (conn==null){
			try{
				Class.forName(nomeDoDriver);
				conn = DriverManager.getConnection(url,username,password);
			} catch ...
			
		} 
		try {
			if (conn.isClosed()){
				try{
					Class.forName(nomeDoDriver);
					conn = DriverManager.getConnection(url,username,password);
				} catch  ...
		}
		return conn;
	}

Isto pode ser melhorado ?

Obrigado,

Márcio

Você precisa de apenas uma conexão para a aplicação Inteira??
Então eu manteria como está.

Quanto ao ThreadLocal, é o seguinte. Eu não tenho nenhum exemplo sobre ThreadLocal comigo agora! Mas da documentação do Hibernate tem uma classe chamada HibernateUtil. Ele armazena os sessions em um objeto do tipo ThreadLocal.

A minha sugestão seria você pegar este código por exemplo, dar uma estuda e aplicar no seu código.

Desta forma, cada thread da aplicação usuário sua própria connection. (Considere que cada thread é um usuário que está utilizando a aplicação naquele momento, certo!! :wink: )

O endereço na net que tem o exemplo é este:
http://www.hibernate.org/hib_docs/v3/reference/en/html/quickstart.html#quickstart-persistentclass

mas para facilitar, vou colocar o código aqui em baixo. É para hibernate, mas não se deixe assustar por isso :wink: .

import org.hibernate.*;
import org.hibernate.cfg.*;

public class HibernateUtil {

    private static Log log = LogFactory.getLog(HibernateUtil.class);

    private static final SessionFactory sessionFactory;

    static {
        try {
            // Create the SessionFactory
            sessionFactory = new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            log.error("Initial SessionFactory creation failed.", ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static final ThreadLocal session = new ThreadLocal();

    public static Session currentSession() {
        Session s = (Session) session.get();
        // Open a new Session, if this Thread has none yet
        if (s == null) {
            s = sessionFactory.openSession();
            session.set(s);
        }
        return s;
    }

    public static void closeSession() {
        Session s = (Session) session.get();
        if (s != null)
            s.close();
        session.set(null);
    }
}

Abraços!
Thiago

Criado 4 de maio de 2005
Ultima resposta 5 de mai. de 2005
Respostas 16
Participantes 7