Exemplo de Uso de Pool de Conexões

4 respostas
mateusviccari

Olá, estou estudando pool de conexões e fiz um método de conexão com o banco de dados usando o Apache Commons DBCP.
Nele, existe uma classe CONEXAO que contém um objeto BasicDataSource.
Nesta classe existem 3 métodos, sendo 1 para inicializar o BasicDataSource, e outros 2 que retornam objetos do tipo Persistencia, um deles sendo uma persistencia pra operações de Insert Update Delete e outro pra operações de Select.
Os objetos Persistencia por sua vez contém um objeto ResultSet, um Connection e um Statement, que são inicializados pelo construtor na classe CONEXAO. É através de cada Persistencia que se executa os SQLs, se da o commit e rollback quando necessários e se fecha as conexões.

A idéia desse método é que cada vez que se queira executar um SQL, seja criado um novo Objeto do tipo Persistencia, seja realizada a execução do ou dos SQLs a partir dessa Persistencia e a seguir seja fechada a Connection e o Statement relacionados à essa Persistencia.

Um exemplo do que eu falei até agora, esta é a classe usada pra testar as conexões. Neste caso, foram incluídos 2 registros usando a mesma Persistencia e foi dado Commit depois de executar os SQLs, para o caso de precisar dar rollback nas 2 operações. Depois foi criado outra persistencia pra gravar mais um registro. E depois disso foi executado o select pra mostrar a tabela.
public class _Testes {

    public static void main(String[] args) {
        CONEXAO.criarConexao();//inicializa o BasicDataSource da classe CONEXAO.
        
        Persistencia r1 = CONEXAO.criarPersistencia_IUD();
        r1.executar("insert into cliente(nome,idade,email) values('Elefante Marrom',28,'[email removido]')");
        r1.executar("insert into cliente(nome,idade,email) values('Elefante Rosa',87,'[email removido]')");
        r1.commit();
        
        Persistencia r2 = CONEXAO.criarPersistencia_IUD();
        r2.executar("insert into cliente(nome,idade,email) values('Tigre Branco',27,'[email removido]')");
        r2.commit();
        
        mostrarAlgunsDados();
    }

    private static void mostrarAlgunsDados() {
        Persistencia x = CONEXAO.criarPersistencia_S("select * from cliente");
        try {
            while(x.rs.next()){
                System.out.println("ID: "+x.rs.getString("id_cliente"));
                System.out.println("Nome: "+x.rs.getString("nome"));
                System.out.println("Email: "+x.rs.getString("email"));
                System.out.println("Idade: "+x.rs.getString("idade"));
                System.out.println("--------------");
            }
            x.fecharConexao();
        } catch (Exception ex) {
            System.out.println(ex.getLocalizedMessage());
        }
    }
}

Eu gostaria de saber a opinião de vocês sobre esse método, se está sendo feito do jeito correto, ou o que eu posso melhorar.

As classes Persistencia e CONEXAO, respectivamente:
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

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

/**
 * Objeto contendo um ResultSet, um Statement e uma Connection.
 * Quando terminar de usar esse objeto, deve-se usar o método fecharConexao(),
 * que vai fechar a conexão associada com aquele ResultSet.
 * @author adm
 */
public class Persistencia{
    ResultSet rs;
    Connection con;
    Statement st;

    Persistencia(ResultSet rs, Connection con, Statement st) {
        this.rs = rs;
        this.con = con;
        this.st=st;
    }
    
    /**Executa um comando SQL. Para gravar este comando, use o metodo commit()
     * @param sql Comando SQL de INSERT, UPDATE ou DELETE.
     */
    public void executar(String sql){
        try {
            st.execute(sql);
        } catch (Exception s) {
            System.out.println(s.getLocalizedMessage());
        }
    }
    
    /**Fecha a conexão e o statement dessa conexão.
     */
    public void fecharConexao(){
        try{
            if(con!=null && !con.isClosed()){con.close();}
            if(st!=null && !st.isClosed()){st.close();} //esse método ja fecha o ResultSet a ele associado.
        }catch(Exception e){
            System.out.println(e.getLocalizedMessage());
        }
    }

    /**Tenta gravar a conexão desta persistencia e logo a seguir fecha os objetos dessa Persistencia.
     */
    void commit() {
        try{
            con.commit();
            fecharConexao();
        }catch(Exception e){
            
        }
    }
    
    /**Tenta cancelar a conexão desta persistencia e logo a seguir fecha os objetos dessa Persistencia.
     */
    void rollback() {
        try{
            con.rollback();
            fecharConexao();
        }catch(Exception e){
            
        }
    }
}

---------

import java.sql.*;
import org.apache.commons.dbcp.BasicDataSource;

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

/**NÃO CRIE uma instancia dessa classe, ao invés disso use o método criarConexao() diretamente.
 * Quando precisar fazer um SELECT, use o método criarPersistencia_S() que retorna uma Persistencia, e percorra
 * o resultSet dessa persistencia com o método next().
 * Quando precisar fazer um INSERT, UPDATE ou DELETE, use o método criarPersistencia_IUD(), a seguir use
 * o método executar() dessa peristencia pra executar comandos e pra gravá-los use o metodo commit da persistencia.
 * usar o commit daquela persistencia.
 */
public class CONEXAO {
    public static BasicDataSource bds;
    
    
    /**Cria uma nova BasicDataSource, que é um Pool de Conexões.
     * Deve-se criar uma Persistencia para cada operação realizada usando os métodos criarPersistencia()
     * dessa classe. Esses métodos irão criar Connections, ResultSets e Statements e vão retorna-los em um objeto
     * do tipo Persistencia. Lembre-se de FECHAR as persistencias criadas quando não precisar mais usá-las,
     * caso contrário elas ficarão abertas e consumindo recursos do Banco, além de que o BasicDataSource possui um
     * limite de conexões ativas(que pode ser alterado).
     */
    public static void criarConexao(){
        bds=new BasicDataSource();
        bds.setDriverClassName("org.postgresql.Driver");
        bds.setUrl("jdbc:postgresql://localhost/testeFrameworkAtualy");
        bds.setUsername("postgres");
        bds.setPassword("masterkey");
    }
    
    /**Retorna um objeto contendo um ResultSet, um Statement e uma Connection.
     * Quando terminar de percorrer o ResultSet deste objeto, deve-se usar o método fecharConexao()
     * daquela persistencia, que vai fechar a Connection, o Statement e o ResultSet associados
     * com a Persistencia retornada.
     * @param sql Comando SQL de consulta no banco de dados
     * @return Uma nova persistencia, usada apenas para operações de SELECT. Lembre-se de FECHAR a persistencia
     * quando não precisar usar mais o ResultSet desta Persistencia.
     */
    public static Persistencia criarPersistencia_S(String select){
        ResultSet rs=null;
        Persistencia x = null;
        try {
            Connection con = bds.getConnection();
            Statement st=con.createStatement();
            rs=st.executeQuery(select);
            x=new Persistencia(rs, con, st);
        } catch (Exception s) {
            System.out.println(s.getLocalizedMessage());
        }
        return x;
    }
    
    /**Retorna um objeto contendo um Statement e uma Connection.
     * Deve ser usado o método commit() dessa persistencia assim que queira gravar os sql executados através
     * do método executar() da persistencia retornada.
     * @return Uma nova persistencia, usada apenas para operações de INSERT, UPDATE e DELETE.
     */
    public static Persistencia criarPersistencia_IUD(){
        Persistencia x=null;
        try {
            Connection con = bds.getConnection();
            con.setAutoCommit(false);
            Statement st=con.createStatement();
            x=new Persistencia(null, con, st);
        } catch (Exception s) {
            System.out.println(s.getLocalizedMessage());
        }
        return x;
    }
    
    
}

4 Respostas

Dakon

Bom dia, acho bastante interessante a ideia de implementar seus próprios métodos, no entanto, nesse caso em específico, já possuímos uma excelente biblioteca, que, dentre outras coisas, realiza persistência; por quê não utilizar Hibernate?

mateusviccari

Eu penso que tem casos que é melhor usar sql puro do que Hibernate, não sou nenhum expert mas acredito que nem sempre Hibernate é a solução…
E no mais, esse metodo é somente pra estudo de Pool de Conexões.
E lembrando que a Persistencia que eu criei não serve pra persistir classes de entidade, ela só executa os SQLs puros e me devolve Resultados(quando houver resultados a serev devolvidos).

Dakon
mateusviccari:
Eu penso que tem casos que é melhor usar sql puro do que Hibernate, não sou nenhum expert mas acredito que nem sempre Hibernate é a solução... E no mais, esse metodo é somente pra estudo de Pool de Conexões. E lembrando que a Persistencia que eu criei não serve pra persistir classes de entidade, ela só executa os SQLs puros e me devolve Resultados(quando houver resultados a serev devolvidos).

Hibernate não é solução pra tudo mesmo. Mas vamos nos ater a seu código. Primeira coisa, na minha opinião, é escolher se codifica em inglês, ou português, fica muito feio essa mistura. Depois Utilizaria PreparedStatement, pela performance, um maior controle de tipagem e a possibilidade de trocar de banco de dados com mais facilidade. Outra coisa que faria era unificar os métodos criarPersistencia_S e criarPersistencia_IUD, afinal de contas, a única diferença prática é o autoCommit mesmo. Também utilizaria o padrão Singleton no instanciador de conexões, evitando correr o perigo de ter várias variáveis static consumindo recursos do sistema. E para finalizar, você está usando o métdo fecharConexao dentro do try, o que pode acarretar, no caso de ocorrer uma exception antes da chamada ao fecharConexao, que sua conexão continue aberta pois o fluxo foi desviado pro catch! Para corrigir, coloque o fecharConexao dentro de um bloco finally após o try:

private static void mostrarAlgunsDados() {  
        Persistencia x = CONEXAO.criarPersistencia_S("select * from cliente");  
        try {  
            while(x.rs.next()){  
                System.out.println("ID: "+x.rs.getString("id_cliente"));  
                System.out.println("Nome: "+x.rs.getString("nome"));  
                System.out.println("Email: "+x.rs.getString("email"));  
                System.out.println("Idade: "+x.rs.getString("idade"));  
                System.out.println("--------------");  
            }              
        } catch (Exception ex) {  
            System.out.println(ex.getLocalizedMessage());  
        } finally { x.fecharConexao(); } 
         
    }
eduardoac

Olá, veja se isso ajuda?

OracleConnectionPoolDataSource ocpds = new OracleConnectionPoolDataSource();

ocpds.setURL(url);
ocpds.setUser(user);
ocpds.setPassword(password);

OracleConnectionCacheImpl ocpdsImpl = new OracleConnectionCacheImpl(ocpds);

ocpdsImpl.setMaxLimit(2);
ocpdsImpl.setMinLimit(2);

Connection = ocpds.getConnection();
Segue o site com alguns exemplos:

http://docs.oracle.com/cd/A97335_02/apps.102/a83724/samapp9.htm

Esta no indice Oracle Connection Cache (dynamic)--Cache1.java

Abraços!

Criado 27 de março de 2012
Ultima resposta 27 de mar. de 2012
Respostas 4
Participantes 3