[RESOLVIDO] Pool de conexão não pega conexão existente!

Fa ai galera, estou implementando um pool de conexão com o C3P0 para evitar de conectar toda hora, mas não está pegando uma unica conexão, ele conecta toda hora com tempo comum, dando continuidade ao problema de conexão:

Utilizei o timemillis para calcular o tempo de conexão na console:

Sistema OK! - Conectado
Tempo: 2911
Conexão Fechada
Conexão Fechada
INSERT: 0-6, -1
22/01/2012 13:16:21 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource getPoolManager
INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 5, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1hge0yt8l1nta9i4d2cft|f47bf5, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1hge0yt8l1nta9i4d2cft|f47bf5, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://meuhost.com.br/bd, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 5, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 1, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
Sistema OK! - Conectado
Tempo: 2992
Conexão Fechada[/code]

Ele repete isso em todas as conexões que faço, ou seja não está aproveitando a conexão existente

minha classe de conexão do pool é:


[code]package dao;
import java.beans.PropertyVetoException;
import java.io.File;  
import java.io.FileInputStream;  
import java.io.IOException;  
import java.sql.Connection;  
import java.sql.PreparedStatement;  
import java.sql.ResultSet;  
import java.sql.SQLException;  
import java.sql.Statement;
import java.util.Properties; 

import Administrador.DadosConn;

import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DaoConexao {
	 private Properties props;
	 ComboPooledDataSource cpds;
	  
	    public DaoConexao() {
	        this.configurarDataSourceRAC();
	    }  
	private void configurarDataSourceRAC() {
		cpds = new ComboPooledDataSource();
		try {
			DadosConn d = new DadosConn();
			cpds.setDriverClass("com.mysql.jdbc.Driver");
			
			cpds.setJdbcUrl(d.getUrl());
			cpds.setUser(d.getUsuario());
			cpds.setPassword(d.getSenha());

			cpds.setMinPoolSize (1);
			cpds.setAcquireIncrement (5);
			cpds.setMaxPoolSize (5);
		} catch (PropertyVetoException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	} 
	  
	public Connection getConexaoRAC(){  
	  
	        try{              
	            return cpds.getConnection();  
	        }catch (SQLException sqle){  
	            sqle.printStackTrace();  
	            return null;  
	        }catch (Exception e){  
	            e.printStackTrace();  
	            return null;  
	        }	  
	    }  
	    public static void liberarRecursosBD(ResultSet rs, Statement ps, Connection conn){  
	        try{  
	            if (ps != null)  
	            	ps.close();  
	            if (rs != null)  
	                rs.close();  
	            if (conn != null)  
	                conn.close();  
	        }catch (SQLException sqle){  
	            sqle.printStackTrace();  
	            
	        }catch (Exception e){  
	            e.printStackTrace();  
	            
	        }  
	  
	    }  
	  
}

E para pegar uma nova conexão eu faço assim:

con = daoConexao.getConexaoRAC();

O que pode esta havendo de errado?

A configuração do ComboPooledDataSource esta errada? ou pode ser melhorada?

Você está sempre fechando a conexão?

to sim sempre fecho a con o stmt eo result set

Niguem do forum nunca mexeu com o c3p0 não? se alguem ai ja tiver mexido me passa um exemplo! Por favor!

Como você sabe que ele não está reusando conexões?

o objetivo do poll seria o reuso d euma conexão certo? ou seja ne cada execução teria uma conexão, mas toda hora conecta noramalmente com o mesmo tempo da primeira conexão, ne todos os métodos das classes DAO eu começo conectado e no final dele eu fecho e com isso algumas classes estão demorando cerca de 50seg para serem executadas, uma completa lentidão!

Você pode mostrar como está fazendo para usar seu pool? Poste o método de uma dessas classes. Preferencialmente, um que tenha a contagem do tempo.

Método de inserção!

public void insere(Patrimonio p1){ conectar(); try { comando.executeUpdate("INSERT INTO patrimonio(numbem, equipamento, modelo, empresa) VALUES ('"+p1.getNumbem()+"', '"+p1.getEquipamento()+"', '"+p1.getModelo()+"', '"+p1.getEmpresa()+"');"); System.out.println("Inserida!"); } catch (SQLException e) { imprimeErro("Erro ao inserir Patrimônio ", e.getMessage()); } finally { fechar(); } }
Método de conectar

private void conectar() { try { long tempoInicio = System.currentTimeMillis(); con = new DaoConexao().getConexaoRAC(); //Connectio con é declarado na no início da classe comando = con.createStatement(); //Mesma coisa pro Statement System.out.println("Sistema OK! - Conectado"); long tempoFim = System.currentTimeMillis(); System.out.println("Tempo: "+(tempoFim - tempoInicio)); } catch (SQLException e) { imprimeErro("Erro ao conectar", e.getMessage()); } }
Método de fechar!

private void fechar() { try { comando.close(); con.close(); System.out.println("Conexão Fechada"); } catch (SQLException e) { imprimeErro("Erro ao fechar conexão", e.getMessage()); } }

E se eu inserir 5 empresas seguidas vai dar sempre 3100 em média o tempo, ou seja está conectando toda hora

Já vi seu problema. Você está fazendo:

new DaoConexao().getConexaoRAC();

Mas isso efetivamente cria um Pool diferente do C3P0 para cada consulta.

Transforme sua classe num Singleton.

ixi essa vc me pegou… como que eu faço isso?

Eis como fica:

[code]package dao;
import java.beans.PropertyVetoException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import Administrador.DadosConn;

import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DaoConexao {
private static DaoConexao instance = new DaoConexao();

private Properties props;
ComboPooledDataSource cpds;
  
private DaoConexao() {	        
}  

public static DaoConexao getInstance() {
    return instance;
}

private void configurarDataSourceRAC() {
    cpds = new ComboPooledDataSource();
    try {
        DadosConn d = new DadosConn();
        cpds.setDriverClass("com.mysql.jdbc.Driver");
		
        cpds.setJdbcUrl(d.getUrl());
        cpds.setUser(d.getUsuario());
        cpds.setPassword(d.getSenha());

        cpds.setMinPoolSize (1);
        cpds.setAcquireIncrement (5);
        cpds.setMaxPoolSize (5);
    } catch (PropertyVetoException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
} 
  
public synchronized Connection getConexaoRAC(){  
    if (cpds == null)
        configurarDataSourceRAC();
  
    try{              
        return cpds.getConnection();  
    }catch (Exception e){  
        e.printStackTrace();  
        return null;  
    }	  
}  

public static void liberarRecursosBD(ResultSet rs, Statement ps, Connection conn){  
    try{  
        if (ps != null)  
            ps.close();  
        if (rs != null)  
            rs.close();  
        if (conn != null)  
            conn.close();  
    }catch (Exception e){  
            e.printStackTrace();  	            
    }  
}  

}
[/code]

E para usar:

private void conectar() { try { long tempoInicio = System.currentTimeMillis(); con = DaoConexao.getInstance().getConexaoRAC(); //Connectio con é declarado na no início da classe comando = con.createStatement(); //Mesma coisa pro Statement System.out.println("Sistema OK! - Conectado"); long tempoFim = System.currentTimeMillis(); System.out.println("Tempo: "+(tempoFim - tempoInicio)); } catch (SQLException e) { imprimeErro("Erro ao conectar", e.getMessage()); } }

Note que agora só existe uma única instância do DaoConexao para a aplicação inteira.
Ou seja, você só dá new uma única vez.

Assim, você está usando sempre o mesmo pool do C3P0.
Seu problema, antes, é que você efetivamente estava criando um pool diferente em cada consulta que executava.

Comecei a intender, nem desconfiei que pode ser isso, eu imaginava que a aplicação criava algo internamente ao c3p0!
Vou testar aqui, agradeço a ajuda. Mas e no caso de chamar outra classe na instancia, funcionaria também? Caso eu chama-se uma classe dao diferente, o objeto continuaria unico?

Se você chamar esse mesmo DaoConexao na outra classe sim.

Note que a instância do DaoConexao é criada uma única vez, numa variável estática.

Deixa eu separar a parte do singleton e comentar para vc entender melhor:

[code]public class DaoConexao {
//Aqui criamos a única DaoConexao do programa.
private static DaoConexao instance = new DaoConexao();

//Note que deixamos o construtor privado, para ninguém fazer new DaoConexao().
private DaoConexao() {}

public static DaoConexao getInstance() {
    return instance; //Aqui a DaoConexao é retornada, sem que seja criada uma nova DaoConexao
}

//Resto dos métodos aqui

}[/code]

Se você quiser ter vários DAOs em sua aplicação, sugiro deixar apenas a criação do Pool em um Singleton.
Esse singleton retornaria o pool para os vários DAOs. E eles se encarregariam de criar a conexão dali em diante.

Entendi, mas se o construtor esta privado qual seria a maneira cera de chama-lo?

[quote=rodrigo73]Comecei a intender, nem desconfiei que pode ser isso, eu imaginava que a aplicação criava algo internamente ao c3p0!
Vou testar aqui, agradeço a ajuda. Mas e no caso de chamar outra classe na instancia, funcionaria também? Caso eu chama-se uma classe dao diferente, o objeto continuaria unico?[/quote]

Não tem nada de internamente. Sempre que você dava um new DaoConexao() um objeto diferente, do tipo DaoConexao() era criado.
Com isso era criado um novo pool do C3P0. E esse DataSource é o seu pool (o nome dele é ComboPooledDataSource).

Então, vc não tinha 1, mas vários pools que reutilizavam conexão. Mas como um pool era criado para cada consulta, as conexões nunca eram reusadas.

Ele só pode ser chamado dentro da classe. Note que a primeira linha da classe, que cria a variável instance, chama o construtor.

Isso garante que essa linha será o único lugar onde o construtor será chamado.

O padrão Singleton visa garantir exatamente isso: que um único objeto da classe será criado no programa inteiro.
Ali, naquele new.

No resto do código, as demais classes só podem acessar a instância já criada através do getInstance().

Intendi… meu pc ta meio lento mas vou testar aqui, aproveitei pra dar uma lida sobre isso na net aqui. Mas agora está bem claro! :smiley:

Ta tudo perfeito agora
Tempo das conexões: 3ms

Obrigado pela grande aula :smiley:
Salvou minha segunda feira… vai dar pra tocar o projeto normalmente agora!