Exemplo usando Connection Pool

Fala galera…

alguem ae teria um exemplinho simples de como usar o DBCP da jakarta??
dei uma olhada nos exemplos lah do site dele, mas tem uns 3 exemplos lah e nao sei qual deles o melhor/ideal p/ usar…

valew

Vc tá utilizando jdbc puro?

eh…apenas JDBC p/ conectar no banco…

Este aqui eu peguei lá mesmo.

Inclua isto no web.xml

<resource-ref> <description>Meu banco</description> <res-ref-name>jdbc/poolDB</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>

isto no context.xml

<ResourceLink name="jdbc/poolDB" type="javax.sql.DataSource" global="jdbc/poolDB"/>

agora no server.xml, colocando a url correta e aclasse correta do drive.

<Resource name="jdbc/poolDB" type="javax.sql.DataSource"/> <Resource name="jdbcDB" type="javax.sql.DataSource"/> <ResourceParams name="jdbc/poolDB"> <parameter> <name>maxWait</name> <value>5000</value> </parameter> <parameter> <name>maxActive</name> <value>4</value> </parameter> <parameter> <name>password</name> <value>prs</value> </parameter> <parameter> <name>url</name> <value>jdbc:mysql://localhost:3306/seubanco</value> </parameter> <parameter> <name>driverClassName</name> <value>org.gjt.mm.mysql.Driver</value> </parameter> <parameter> <name>maxIdle</name> <value>2</value> </parameter> <parameter> <name>username</name> <value>root</value> </parameter> </ResourceParams>
Esta parte do server.xml o proprio tomcat pode fazer pra você. Entre no admin do tomcat e crie um data source lá passando a url e o drive. Usei a versão 5.028.

cria uma classe para criar as conexões.

[code]/*

  • Connection.java
  • Created on 31 de Outubro de 2004, 16:12
    */

import java.sql.Connection;
import javax.sql.DataSource;
import javax.naming.Context;
import javax.naming.InitialContext;
import java.sql.SQLException;
import javax.naming.NamingException;
/**
*

  • @author regis
    */
    public class Pool {
    public Pool() {
    }
    public static Connection getConnection() {
    Connection conn = null;
    try {
    Context ctx = (Context) new InitialContext().lookup(“java:comp/env”);
    conn = ((DataSource) ctx.lookup(“jdbc/poolDB”)).getConnection();
    } catch (Exception e) {
    e.printStackTrace(System.err);
    }
    return conn;
    }
    }[/code]

e usa ela assim:

con = Pool.getConnection();

Antes que você pense que há muito código, isto é o mínimo que precisa.

Espero ter ajudado, abraço.

Olá

Uma dica: para entender o DBCP é preciso entender também do jakarta-commons-pool. Baixe este cara e veja a API. Depois veja como configurar um DataSource com JNDI no tomcat. Os ResourceParams do server.xml são aqueles que fazem sentido com seu pool (no caso, dbcp e pool).

[]s
Luca

Bem, todo mundo já respondeu… mas vale a pena dar uma olhadinha aqui se tiver dúvidas.

valew pelas dicas, turma…

mas to usando o WAS como AppServer, nao tomcat…

mas valew…

Estou usando o exemplo mais simples que peguei no próprio site do projeto.
Não usei nenhuma configuração xml. Está funcionando bem.

import javax.sql.DataSource;
import java.sql.;
import org.apache.commons.dbcp.BasicDataSource;
import java.util.Properties;
import java.io.
;
import javax.servlet.ServletContext;

public class Dbpc {
private static Dbpc instance = null;
private DataSource ds;
private Connection con;
private String driver;
private String url;
private String login;
private String password;
private int maxConnections;
private long maxWait;

/** Creates a new instance of Dbpc */
public Dbpc() {
    Properties props = new Properties();
     try {
     
        InputStream fis = this.getClass().getClassLoader().getResourceAsStream("db.properties");                        
        props.load(fis);            
        fis.close();
    }
    catch(FileNotFoundException f) {
        System.out.println("File not found in Dbcp --> constructor.

" + f.getMessage());
f.printStackTrace();
}
catch(IOException ioex){
System.out.println("Error I/O in Dbpc --> constructor.
" + ioex.getMessage());
ioex.printStackTrace();
}
catch(Exception e) {
System.out.println("Error in Dbpc --> constructor.
" + e.getMessage());
e.printStackTrace();
}

    //recuperando configuracoes de acesso ao db           
    driver = props.getProperty("driver");
    url = props.getProperty("url");
    login = props.getProperty("login");
    password = props.getProperty("password");
    maxConnections  = (new Integer(props.getProperty("maxConnections"))).intValue();
    maxWait = (new Long(props.getProperty("maxWait"))).longValue();        
    ds = setupDataSource();
}

public static Dbpc getInstance() {
  if(instance == null) {
     instance = new Dbpc();
  }
  return instance;
}

public Connection getConn() throws SQLException {
    return ds.getConnection();        
}

private DataSource setupDataSource() {
    BasicDataSource ds = new BasicDataSource();
    ds.setDriverClassName(driver);
    ds.setUsername(login);

    ds.setPassword(password);
    ds.setUrl(url);
    ds.setMaxActive(maxConnections);
    ds.setMaxWait(maxWait);
    ds.setDefaultAutoCommit(true);
    return ds;
}

public void printDataSourceStats() throws SQLException {
    BasicDataSource bds = (BasicDataSource) ds;
    System.out.println("NumActive: " + bds.getNumActive());
    System.out.println("NumIdle: " + bds.getNumIdle());
}

/*shutdown DataSource*/
public void shutdown() throws SQLException {
    BasicDataSource bds = (BasicDataSource) ds;
    bds.close();
}

}

Olá

Wendel, ótimo exemplo. Mas ficaria mais legal com identação entre Code e /Code. Veja dicas em: http://www.guj.com.br/forum/viewtopic.php?t=16594

[]s
Luca

valew pelas dicas pessoal…

mas eh o seguinte…o proprio WAS jah tem como implementar o Pool no servidor…
como banco, vou usar o DB2 e no pacote JDBC dele vi umas classes tb p/ fazer Pool…

ai fica a duvida…fazer ou nao no codigo o Pooling?? sera melhor deixar o servidor tratar disso??

Em servidores de aplicações (como o WAS, o Sun Java System, o JBoss etc.) normalmente a gente só obtém uma conexão a partir de um java.sql.DataSource, e a implementação de DataSource é que faz o connection pooling. Para devolver a conexão ao pool de conexões, basta fechá-la corretamente.
A única coisa chata é que a Connection que o DataSource retorna é aquela Connection bastante genérica; se você precisa usar algum recurso do banco de dados que não está exposto via JDBC puro, você precisa fazer umas mágicas.
Por exemplo, teve uma vez que tive de passar BLOBs como parâmetros para stored procedures no Oracle e também ARRAYs e objetos Oracle, e isso só consegui fazer direitinho (incluindo o problema da limitação de tamanho de BLOBs…) usando oracle.jdbc.internal.OracleConnection e outras rotinas no pacote oracle.jdbc; então tive que fazer uma pequena mágica - normalmente o objeto Connection retornado pelo DataSource é um wrapping da conexão “nativa” para o banco. Então tive de checar se o objeto Connection retornado pelo DataSource era um org.jboss.resource.adapter.jdbc.WrappedConnection (no caso do JBoss), e se fosse, ele tem um método getUnderlyingConnection, que retorna a conexão como um objeto oracle.jdbc.internal.OracleConnection.

só de usar Singleton com DAO ja não cria um pool por assim dizer?

Hum… eu acho que o conceito de um pool de conexões vai muito além de um “acessa-o-banco-e-manda-pra-ca”. Um pool vai estar gerenciando não só o request de conexões, mas também a quantidade de conexões ativas, a configuração do DataSource, e dentro de cada uma destas, muitas outras configurações.

Em nosso projeto, estamos usando o c3p0 que está dando conta do recado muito bem. Sua configuração é trivial e ele faz tudo de maneira muito transparente. Acho que é uma boa saida.

Rubens Microfilo, o conceito de Singleton não está descartado, afinal o pool deve ser único :wink:

(:

hum

legal

digamos que eu esteje usando DAO e singleton

digamos que eu queira limitar o numero de conexão ha 17 conexões simultaneas

o que vcs acham dessa solução

public class ConexaoDAO
{

private static ConexaoDAO instancia = null;
private static int numConexoes = 0;
private static final int MAX_CONEXOES = 17;

private ConexaoDAO()
{
//código para conectar ao BD
//bla bla bla bla bla 
//bla bla bla
//bla bla bla
}

public static ConexaoDAO getConexaoDAO() throws TooManyConnectionsException
{

if (nunConexoes >= MAX_CONEXOES)
{
  throws new TooManyConnectionsException("ERRO! MUITAS CONEXÕES", MAX_CONEXOES);
}
numConexoes++;
if (instancia  == null)
 instancia = new ConexaoDAO;
return instancia
}


//getters...
}

seria uma coisa assim?

PS: Meu nome é RubeM (primogênito de Jacó), não RubeNS(piloto de F1) :lol:

Singleton = ruim. Use um pool de verdade. :wink:

Só cuidado no decremento da variável de contagem.

Olha um exemplo meu com o c3p0

[code]/*

  • Criado em Dec 30, 2004
  • Lucas Frare Teixeira
  • lteixeira@filadelfia.br
    */
    package br.filadelfia.connection;

import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;

import org.apache.log4j.Logger;

import com.mchange.v2.c3p0.ComboPooledDataSource;

/**

  • @author Lucas Teixeira - <a
  •     href="mailto:lteixeira@filadelfia.br">lteixeira@filadelfia.br </a>
    

*/
public class ConnectionPool {

static Logger log = Logger.getLogger(ConnectionPool.class); 
private static ComboPooledDataSource cpds;

private ConnectionPool() {
	//Singleton é bonito
}

public static Connection getConnection() throws PropertyVetoException, SQLException  {
	if (cpds == null) {
        cpds = new ComboPooledDataSource();
        cpds.setDriverClass("org.gjt.mm.mysql.Driver");
        cpds.setJdbcUrl("jdbc:mysql://localhost:3306/dbunifil");
        cpds.setUser("root");
        cpds.setPassword("root");
        cpds.setMinPoolSize(10); 
        cpds.setAcquireIncrement(5); 
        cpds.setMaxPoolSize(50);
        cpds.setAcquireRetryAttempts(3);
        //cpds.setMaxIdleTime(60);
    }
    log.info("Pool forneceu conexão.");
    return cpds.getConnection();
}

}[/code]

Mal pelo nome.

CV: o pool não é o controle do numero de conexões??? o que falta na minha classe para se tornar um poorl de conexões?

Um pool de conexões não controla somente o número de conexões que devem ser estabelecidas. Além disso, ele ainda deve controlar o timeout das conexões, fechamento de conexões inativas por um determinado tempo, etc…

[]'s

a tAh…

vai além do meu conhecimento no momento…

[quote=microfilo]a tAh…

vai além do meu conhecimento no momento…[/quote]

Para isso existem APIs prontas de implementações de Pool… o c3p0 faz tanta coisa, e tudo de um modo tão transparente. Capaz de usar uma camiseta: “c3p0, foi bom para vc tb?”