Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

Pool de Conexões e Instâncias de Database

Estava reparando a seguinte situação:

Utilizando os exemplos das aulas e aplicando em um outro projeto meu, fiz a classe Database bem semelhante a dos exemplos, mas utilizando o C3P0 para PoolConnection e MySQL como banco de dados.

Reparei que, a cada nova instância de Database, estamos criando um novo Pool de conexões e abrindo conexões, as quais não são fechadas pois estão em pool.

Então se chamo mais de uma classe que cria um objeto Database, estou criando vários Pools e deixando várias conexões abertas. Ocorre o mesmo se eu estiver usando um projeto web, que é o meu caso (Com Servlets).

Qual seria a melhor prática nesse caso? Fazer o atributo pool da classe Database ser estático e só instanciá-lo quando for null? Fechar o pool de conexões quando o objeto Database for "destruído"? Ou nenhuma dessas opções seria uma boa prática e o ideal seria fazer de outro modo?

5 respostas

Bom dia Ricardo, pode postar suas classes por favor?

Olá Guilherme, seguem um exemplo de como está hoje, mas usei o atributo como estático justamente pra não ocorrer o problema que citei na pergunta:

PS: dei uma simplificada em partes não relevantes.

Classe Database:

package br.com.ricardosander.meupetshop.database;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.DataSource;

public class Database {

    private static DataSource pool;

    public Database() throws SQLException, PropertyVetoException {

        if (Database.pool == null) {
            String host = null;
            int port = 0;
            String database = null;
            String user = null;
            String password = null;

            //Lé configurações de um arquivo....

ComboPooledDataSource pool = new ComboPooledDataSource();
            pool.setDriverClass("com.mysql.jdbc.Driver");
            pool.setJdbcUrl("jdbc:mysql://" + host + ":" + port + "/" + database);
            pool.setUser(user);
            pool.setPassword(password);
            pool.setMinPoolSize(1);
            pool.setAcquireIncrement(5);
            pool.setMaxPoolSize(20);

            Database.pool = pool;
        }

    }

    public Connection getConnection() throws SQLException {
        return Database.pool.getConnection();
    }

}

Um model de exemplo

package br.com.ricardosander.meupetshop.model;

public class Pet {

    private long id;

    private String name;

    //outros atributos, construtores, getters e setters.....
}

Uma DAO de exemplo

package br.com.ricardosander.meupetshop.dao;

import br.com.ricardosander.meupetshop.database.Database;
import br.com.ricardosander.meupetshop.model.Pet;
import br.com.ricardosander.meupetshop.model.User;

import java.sql.*;
import java.util.LinkedList;
import java.util.List;

public class MySQLPetDAO  {

    public List<Pet> find(User user) {

        LinkedList<Pet> pets = new LinkedList<>();

        StringBuilder sqlBuilder = new StringBuilder();

        sqlBuilder
                .append("   SELECT ")
                .append("       A.ID ")
                .append(" ,     A.NOME ")
                .append("  FROM animal A ")
                .append("   WHERE A.USUARIO = ? ");

        String sql = sqlBuilder.toString();

        try (
                Connection connection = new Database().getConnection();
                PreparedStatement preparedStatement = connection.prepareStatement(sql)
        ) {

            preparedStatement.setLong(1, user.getId());

            if (preparedStatement.execute()) {

                ResultSet resultSet = preparedStatement.getResultSet();
                while (resultSet.next()) {

                    pets.add(
                            new Pet(
                                    resultSet.getLong("ID"),
                                    resultSet.getString("NOME"),
                                    )
                    );
                }

            }

        } catch (SQLException | PropertyVetoException e) {
            System.out.println("Erro ao conectar no banco de dados ou realizar query.");
            e.printStackTrace();
        }

        return pets;
    }

    @Override
    public Pet find(User user, long id) {

        StringBuilder sqlBuilder = new StringBuilder();

        sqlBuilder
                .append("   SELECT ")
                .append("       A.ID ")
                .append(" ,     A.NOME ")
                .append("  FROM animal A ")
                .append("   WHERE A.USUARIO = ? AND A.ID = ? ");

        String sql = sqlBuilder.toString();

        try (
                Connection connection = new Database().getConnection();
                PreparedStatement preparedStatement = connection.prepareStatement(sql)
        ) {

            preparedStatement.setLong(1, user.getId());
            preparedStatement.setLong(2, id);

            if (preparedStatement.execute()) {

                ResultSet resultSet = preparedStatement.getResultSet();
                if (resultSet.next()) {

                    return new Pet(
                            resultSet.getLong("ID"),
                            resultSet.getString("NOME")
                    );
                }

            }

        } catch (SQLException | PropertyVetoException e) {
            System.out.println("Erro ao conectar no banco de dados ou realizar query.");
            e.printStackTrace();
        }

        return null;
    }

    public boolean insert(Pet pet) {
//implementação do insert omitida...
        return false;
    }

    public boolean remove(Pet pet) {
        //implementação do insert omitida...
        return false;
    }

}

Minhas dependências Maven, caso necessário:

 <dependencies>

        <!-- API de Servlets -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>

        <!-- API jstl -->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <!-- Driver MySQL -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.44</version>
        </dependency>

        <!-- Biblioteca para gerenciamento de Pool de conexões. -->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>

    </dependencies>
solução!

Boa tarde Ricardo, entendi sua ideia. Agora ia te falar para dar uma lida sobre a criação de ds e pool no seu servidor (tomcat ou wildfly) assim tira a sua responsabilidade de se preocupar com isso e joga pra eles

Ok, muito obrigado pelas dicas Guilherme.