Excesso de conexões no banco de dados

boa tarde.

tenho um programa de suporte técnico (helpdesk) aq na empresa onde trabalho que eu fiz. só que tenho um problema na minha conexão, toda vez que atendo um chamado novo, ele abre novas conexões no bd. Quando atendo muitos chamados, ele adiciona muitas conexões no banco de dados. Há mais um programa que compartilha o mesmo servidor, então acaba lotando o numero de conexões. Há alguma forma do meu programa gerar menos conexões?

Segue o código abaixo.

package utilitarios;
import java.sql.*;
import javax.swing.*;


public class conexao
{
final private String driver = "com.mysql.jdbc.Driver"; //aula 29
    final private String url ="jdbc:mysql://localhost:3306/hospital";
    final private String usuario ="usuario";
    final private String senha = "12345";
    private Connection conexao;
    public Statement statement;
    public ResultSet resultset; 
    
 public boolean conecta()
 {
     boolean result = true;
     try
     {
         Class.forName(driver);
         conexao = DriverManager.getConnection(url, usuario, senha);
        // JOptionPane.showMessageDialog(null,"Conectou!");
                         
     }
     catch(ClassNotFoundException Driver)
     {
         JOptionPane.showMessageDialog(null,"Driver não localizado: "+Driver);
         result = false;
     }
     catch(SQLException Fonte)
     {
         JOptionPane.showMessageDialog(null,"Ocorreu um erro na conexão " +
                "com a fonte de dados: "+Fonte);
         result = false;
         
     }
     
     return result;
}

public void desconecta()
{
    boolean result = true;
    try
    {
        conexao.close();
        JOptionPane.showMessageDialog(null,"Banco fechado");
    }
    catch(SQLException fecha)
    {
        JOptionPane.showMessageDialog(null,"Não foi possível fechar "+
                "o banco de dados: "+fecha);
        result = false;
    }
}    

public void executasql(String sql)
{
    try
    {
        statement = conexao.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
        resultset = statement.executeQuery(sql);
    }
    catch(SQLException sqlex)
    {
        JOptionPane.showMessageDialog(null,"Não foi possível "+
                "executar o comando, "+sqlex+", o comando passado foi: "+sql);
    }
}

}

Aqui é uma tela do programa, eu estou chamando a minha classe de conexão.

[code]
public hd_server() {
initComponents();

    con_setores = new conexao();
    con_setores.conecta();
    
    con_hdsf = new conexao();
    con_hdsf.conecta();
   
    con_atualiza = new conexao();
    con_atualiza.conecta();
    
    con_ordena = new conexao();
    con_ordena.conecta();
    
    con_ordatual = new conexao();
    con_ordatual.conecta();
    
    
    [/code]

Cada chamada dessa é uma conexão nova, é o que faz lotar o banco.

Agradeço a ajuda de todos.

Até mais

a) Você criou o método desconecta, quem é que chama esse método? Quando ele é chamado?

b) Para esse tipo de problemas, é aconselhável usar pools de conexões. Só não se esquecer que, depois de usar uma conexão do pool, você deve fechá-la o mais rápido possível (ou seja, devolvê-la ao pool).

Antes de mais nada, obrigado pela resposta. Vamos as respostas.

a) Então meu amigo, eu peguei esse código de uma video aula, sou meio iniciante ainda em java. O cara criou a conexão desconecta mas não ensinou a usar. Toda vez que fecho a conexão, dá pau no programa.

b) Ouvi falar de pool de conexão mas não sei usar ainda, poderia me indicar um link para eu dar uma estudada?

grato!

Olá Boa Tarde, hishin

Eu colocaria a conexão em uma classe ConnectionFactory, sendo assim uma fabrica de conexões…

public class ConnectionFactory {   
  
    public Connection getConnection() {   
  
        try {   
            return DriverManager.getConnection("jdbc:mysql://localhost/fj21", "root", "");   
        } catch(SQLException e) {   
            throw new RuntimeException(e);   
        }   
    }   
} 

Colocaria no no contrutor da classe de manipulação a Conexão…sendo assim você não se preocupa em ficar instanciando a todo momento…


public class ContatoDAO {   
    private Connection connection;   
  
    public ContatoDAO() {   
        try {   
            this.connection = new ConnectionFactory().getConnection();   
        } catch (SQLException e) {   
            throw new RuntimeException(e);   
        }   
    }   

E na hora de manipular o metodo você já fecha a conexao após o uso…

public void adiciona(Contato contato) {   
        try {   
            String sql = "insert into contatos (nome, email, endereco, dataNascimento) values (?,?,?,?)";   
            PreparedStatement stmt = connection.prepareStatement(sql);   
             //Set/Get do que você precisa 
            stmt.execute();  //Executa o que você quiser 
            stmt.close();   //Fecha o que estiver sendo executado...Conexão
        } catch (SQLException e) {   
            throw new RuntimeException(e);   
        }   
    }   

Espero ter te ajudado…

abraços

orras!! terei que mudar todo o codigo, mas tentarei sim. vlw!

vo testar e depois eu posto aqui.

ate mais.

PS: Se alguem tiver mais idéias, posta ai.

hishin, você não pode manter as conexões abertas o tempo todo.

O correto é abrir a conexão, fazer a consulta, guardar os dados num objeto ou mesmo num List ou Map e fechar a conexão, e usar os dados vindos desse objeto, mas nunca manter a conexão aberta.

E um rápido aviso, o código do AndreSorge tem um problema, pois se ocorrer uma exceção a conexão não será fechada, então vai uma regra: sempre feche conexões no bloco finnaly

Então amigo, ouvi falar desse list, mas não sei como usar. acho que o que o AndreSorge é um list não é?

o que seria um Map?

vlw!!

Opa pessoal é isso mesmo, desculpe fiz código na mão e acabei deixando de fora isso…sempre finalize o bloco Try/cath com o finally bem lembrado pelo juliofsn

Abaixo segue um exemplo de um List

public List<Contato> getLista() {
		try {
			List<Contato> contatos = new ArrayList<Contato>();
			PreparedStatement stmt = this.connection.prepareStatement("select * from contatos");

			ResultSet rs = stmt.executeQuery(); //Executa o select

			while(rs.next()) { //Roda até chegar no final do select
				Contato contato = new Contato();
				//popula o objeto contato
				contato.setId(rs.getLong("id"));
				contato.setNome(rs.getString("nome"));
				contato.setEmail(rs.getString("email"));
				contato.setEndereco(rs.getString("endereco"));

				//popula a data de nascimento do contato, fazendo a conversao
				Calendar data = Calendar.getInstance();
				data.setTime(rs.getDate("dataNascimento"));
				contato.setDataNascimento(data);

				//adiciona o contato na lista
				contatos.add(contato);
			}

			return contatos; //Retorna o objeto populado
		} catch (SQLException e) {  //Erro no Select
			throw new RuntimeException(e);  
			rs.close();
			stmt.close();
		}finally{ 
			rs.close(); //Fecha o ResultSet
			stmt.close();   //Fecha a conexão
		}
	}

Espero ajudar…abraços a todos…

boa tarde!

vlw pelas respotas. Mas tenho um problema hehe.

Esse list eh um método nao é? então… ele dá erro qdo adiciono no meu código.

Esse aq é o método que criei baseado no q foi passado aq. Mas ele dá erro sozinho e fiz os imports que o netbeans pede.

public List<cad_user> getLista() {
        try {
            List<cad_user> contatos = new ArrayList<cad_user>();
            PreparedStatement stmt = conexao.prepareStatement("select * from contatos");

            ResultSet rs = stmt.executeQuery(); //Executa o select

            while(rs.next()) { //Roda até chegar no final do select
                cad_user contato = new cad_user();
                //popula o objeto contato
                contato.setId(rs.getLong("id"));
                contato.setNome(rs.getString("nome"));
                contato.setEmail(rs.getString("email"));
                contato.setEndereco(rs.getString("endereco"));

                
                

                //adiciona o contato na lista
                contatos.add(contato);
            }

            return contatos; //Retorna o objeto populado
        } catch (SQLException e) {  //Erro no Select
            throw new RuntimeException(e);
            con_login.resultset.close();;
            con_login.statement.close();
        }finally{
            con_login.resultset.close(); //Fecha o ResultSet
            con_login.statement.close();   //Fecha a conexão
        }
    }

oq está acontecendo?

vlw!!

Manu, faz o seguinte tem como mandar o erro do List?

Você ta importando do java.util*
?

A mensagem de erro é: “missig return statement”

Gostaria de perguntar também onde são criados os métodos utilizados para popular o objeto (setId, por exemplo).

Obrigado pela ajuda.

Opa vamos lá então…eu copiei o seu código e fiz em casa…olhá só…vamos tirar o bloco Finally por enquanto, pois ele tava dando erro aqui em casa também…aqui não deu esse erro que você disse manu…
olha só vou postar aqui 3 classes…ConnectionFactoryContato…e ContatoDao

ConnectonFactory

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;


public  class ConnectionFactory {     

	public Connection getConnection() {     

		try {     
			return DriverManager.getConnection("jdbc:mysql://localhost/fj21", "root", "");     
		} catch(SQLException e) {     
			throw new RuntimeException(e);     
		}     
	}     
}

Contato

import java.util.Calendar;


public class Contato {

	private long id;
	private String nome;
	private String email;
	private String endereco;
	private Calendar dataNascimento;
	
	public Contato(){
		
	}
	
	public Calendar getDataNascimento() {
		return dataNascimento;
	}

	public void setDataNascimento(Calendar dataNascimento) {
		this.dataNascimento = dataNascimento;
	}

	public long getId() {
		return id;
	}
	public void setId(long id) {
		this.id = id;
	}
	public String getNome() {
		return nome;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getEndereco() {
		return endereco;
	}
	public void setEndereco(String endereco) {
		this.endereco = endereco;
	}
}

Você perguntou de onde veio o SetId e os Outro correto? Então e com eles os Set/Get que agente manipula as variáveis…
Entendeu?

ContatoDao

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;


public class ContatoDao {

	private Connection con;

	public ContatoDao() throws SQLException{
		this.con = new ConnectionFactory().getConnection();
	}


	public List<Contato> getLista() {  
		try {  
			List<Contato> contatos = new ArrayList<Contato>();  
			PreparedStatement stmt = this.con.prepareStatement("select * from contatos");  

			ResultSet rs = stmt.executeQuery(); //Executa o select  

			while(rs.next()) { //Roda até chegar no final do select  
				Contato contato = new Contato();  
				//popula o objeto contato  
				contato.setId(rs.getLong("id"));  
				contato.setNome(rs.getString("nome"));  
				contato.setEmail(rs.getString("email"));  
				contato.setEndereco(rs.getString("endereco"));  

				//popula a data de nascimento do contato, fazendo a conversao  
				Calendar data = Calendar.getInstance();  
				data.setTime(rs.getDate("dataNascimento"));  
				contato.setDataNascimento(data);  

				//adiciona o contato na lista  
				contatos.add(contato);  
				rs.close();  
				stmt.close();  
			}  

			return contatos; //Retorna o objeto populado  
		} catch (SQLException e) {  //Erro no Select  
			throw new RuntimeException(e);    
		}  
	}  	
}

Se você copiar e colar desse jeito ele não deve dar erro nenhum…acabei de testar aqui em casa…copia e cola…não dando erro ou dando erro você posta que agente coloca o bloco finally e encerra a conexão e o ResultSet…

Vlw Abraços, posta ai o resultado…

Obs.: Não se esqueça do Driver do MySql…

Melhorando…

Sempre que você ultiliza o Try/Catch tem que ter o bloco Finaly…independente o que aconteça o bloco Finaly sempre será executado…

boa tarde.

Caro AdreSorge, muito obrigado pela sua ajuda.

Agora vamos aos detalhes hehe.

A classe deu certo, não aparece erro, porém… como eu puxo os dados nos formulários? poderia me dar um pequeno exemplo? (se não for pedir demais :slight_smile: )

Muito grato pela ajuda!!

até mais

Esse form que você está falando seria o em que? Swing ou Web?

Você consegue popular os objetos?

Vamos ao um exemplo bem tosqueira…

public class TestaContato{
        
      Contato con = new Contato(); /*Instancia um Contato*/
      ContatoDao conDao = new ContatoDao();/*Instancia um ContatoDao*/

      con.setNome(JOptionPane.showInputDialog("Digite um nome: "));/*Neste ponto você já está "populando" a variável*/
      /*.....*/
      System.out.println(con.getNome());/*Você irá imprimir no console o nome que você digitou no JOptionPane*/ 

      conDao.inserirNoBanco(con); /*Você passa o objeto já populado para o método "inserirNoBanco" que já está esperando o Contato*/

Entendeu? Se ficou qualquer duvida, posta ai que eu tento te dar mais alguns exemplos…

boa tarde.

Meu software é swing.

Então cara… meu programa está cheio de bugs… e terei que tratar desses erros até fazer algo funcionar. Pelo menos consegui ele abrir o formulario. eu tenho um método que chama “mostrar dados”, onde quando eu abro a tela, o formulario já carrega os dados. O método não está funcionando, ele carrega zerado.

mas isso eu estou vendo aq. na semana que vem eu posto aq novamente.

Muito grato pela sua ajuda!

Até mais!

Esse método Mostrardados() ele é um select no banco e monta um List correto?

Vou fazer um bem legal com Swing…ai eu posto aqui para você…

abraços e até mais…

Bom dia, tentei fazer algo assim:

public void mostrar_dados()
    {
         try
        {
            
            Usuario us = new Usuario();
            UsuarioDao usDao = new UsuarioDao();
            usDao.getLista();
            tf_codigo.setText(Integer.toString(us.getId()));
            tf_nome.setText(us.getNome());
            tf_senha.setText(us.getSenha());
            cb_acesso.setSelectedItem(us.getNivel());
           
            
           
        }
        catch(SQLException erro)
        {
              JOptionPane.showMessageDialog(null, "Não localizou dados "+erro);
         }

Mas tenho quase certeza de que está errado, pois apesar de não apontar nenhum erro ele não puxa os dados.

Muito grato pela ajuda.

Até Mais.

Opa manu, vamos tentar assim…

Criando uma classe de modelo…

public class Cliente{
     
     private String nome;
     private int idade;

    public Cliente(){  /*Contrutor*/
    }

        /*Métodos Set's/Get's é com ele que agente manipula os dados*/
        /*Set você utiliza para "Colocar ou Setar" algum valor recebido dentro de uma determinada variável*/
        /*Get você utiliza para "Pegar" algum valor contido dentro de uma determinada variável*/

    public void setNome(String nome){ /*Método que recebe uma String nome*/
             this.nome=nome;      /*"Seta" o valor que veio como parâmetro, dentro da variável 'nome' da classe Cliente*/
    }

    public String getNome(){ /*Não recebe nada como parâmetro*/
             return nome;      /*Retorna o que estiver na variável 'nome' da classe Cliente*/
    }

   public int setIdade(int idade){
              this.idade=idade;
   }
 
    public void getIdade(){
            return idade;
    }
}

Bom já temos as variáveis, agora temos de popular elas correto?, então vamos lá:

public class TestaCliente {

            public static void main(String arg[]){

                 Cliente cliente = new Cliente();/*Criamos uma variável do tipo Cliente, então todo o modelo de cliente está dentro dela*/
                 /*Se você quiser ver se está tudo certo, digite cliente. de um CTRL + Barra de espaço, ele irá trazer todo os métodos nativos e mais os que você criou (Set/Get)Vamos testar?*/
                 cliente.setNome(JOptionPane.showInputDialog("Digite o seu nome: "));/*Neste ponto o que você digitar irá ser inserido na variável nome da classe Cliente, por causa do Set*/
                 cliente.setIdade(Integer.parseInt(JOptionPane.showInputDialog("Digite a idade: ")));

                 ClienteDao clienteDao = new ClientesDao();

                 clienteDao.adiciona(cliente);
              }
}      

Beleza, até agora só criamos a classe de modelo…agora vamos para uma conexão com o banco de dados…

import  java.sql.Connection;         
import java.sql.DriverManager;         
import java.sql.SQLException;         
           
public  class ConnectionFactory {             
         
     public Connection getConnection() { /*Método que retorna uma conexão*/             
         
        try {             
            return DriverManager.getConnection("jdbc:mysql://localhost/fj21", "root", ""); /*fj21 = nome do banco de dados, root = usuário do bando e "" a senha do bando de dados  */           
        } catch(SQLException e) {/*Tratamento de erro*/             
            throw new RuntimeException(e);             
        }             
    }   

Maravilha, já temos uma classe de modelo, e já estamos conectando no banco de dados…agora vamos fazer uma classe DAO, que irá inseri e selecionar alguns dados no banco…

public class ContatoDAO {   
    private Connection connection;   /*Variável do tipo Connection*/
  
    public ContatoDAO() {   /*Contrutor, colocamos a conexão nelo, pois assim todos os métodos desta classe possam utilizar a conexão, sem precisar instanciar a todo momento*/
        try {   
            this.connection = new ConnectionFactory().getConnection();/*Executa o método getConnection da classe ConnectionFactory*/   
        } catch (SQLException e) {   /*Caso de algum erro*/
            throw new RuntimeException(e);   
        }   
    }   
       
       
    public void adiciona(Cliente clie) { /*Método que está recebendo uma variável do tipo Contato*/  
        try {   
            String sql = "insert into cliente (nome, idade) values (?,?)"; /*Neste ponto você cria uma variável do tipo String que recebe como parâmetro a query SQL*/ 
            PreparedStatement stmt = connection.prepareStatement(sql); /*O PreparesStatement é que faz a execução da String Sql, mais para isso ela precisa da conexão*/   
  
            /*Aqui é aonde eu acho que você está amarrado...*/
            /*Vou explica icone por icone: stmt = variável do tipo PreparedStatement já carregada com a conexão e a String sql no gatinho. o setString representa que você irá colocar na String sql um valor do tipo texto (String), lembra que eu comentei que tudo que estiver dentro do () do set, é o que ele tentara "setar" em algum lugar? neste caso é a mesma coisa, ele irá pegar o valor que estiver dentro da variável nome da classe Cliente pelo método getNome(), e você deve estar se perguntando que raios de número 1 é esse ai....bom se você repara na String sql, tem umas ?,? cada numero significa uma ?, então de tivermos 30 ? teremos de 1 a 30 realizando os set's adequado. Sendo mais rápido o que ele irá fazer eh isso: String sql = "INSERT INTO cliente (nome, idade) values ('João', 12);"...entendeu????*/
            stmt.setString(1, clie.getNome());   
            stmt.setString(2, clie.getIdade());   
              
            stmt.execute();/*Neste ponto ele irá executar o comando SQL dentro do bando de dados*/   
            stmt.close();   /*fecha a conexão*/
        } catch (SQLException e) {   /*Caso de algum erro na execução das instruções acima*/
            throw new RuntimeException(e);   /*Captura o erro em tempo de execução*/
        }   
    }   

Entendeu? Caso não fala ai manu que eu tento te dar outro exemplo…

no código que você fez, você está tentando pegar o retorno do select e depois setar nas variaveis…entendeu?

Bom dia. blz??

As classes que vc passou funcionaram mas ainda assim tenho problemas, pois como é muito novo esse tipo de estrutura do código, ainda estou com dificuldades.

vamos lá!

o meu método “mostrar-dados” é um modo q exibe os dados nos campos do formulário assim que ele carrega, porém com esse novo modo ainda não consegui exibi-los.

Meu projeto já está pronto e tenho dados no banco, o problema está na hora de carregar os dados, ainda não testei o gravar/alterar/excluir. assim q eu conseguir fazer funcionar esse método “mostrar-dados” funcionar, partiremos pra proxima etapa.

Grato pela sua ajuda e paciencia.

abraços!