Erro no fechamento de conexões JDBC

13 respostas
W

Bom dia,

Estou tendo problemas ao tentar fechar minhas conexões com o Oracle, mesmo fazendo todos os procedimentos para o fechamento das sessões elas não param de aumentar e só fecham quando eu paro a minha aplicação.
O que ocorre é que quando acontece alguma exceção no meu código, por algum motivo a conexão não é fechada e como o sistema trabalha com threads o número de sessões no banco só aumentam.
Não sei se consegui explicar corretamente, mas coloco abaixo parte do código que escrevi.

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class operacaoDao{

	public String findOperacao(String numSerial, Boolean status) throws SQLException{
		ResultSet rs = null;
		PreparedStatement ps = null;
		if(this.con == null || this.con.isClosed())
			this.con =OracleSqlBase.getConnection();
		try{
			String sql = "SELECT o.id, o.status, o.local FROM operacoes o  WHERE o.num_serial = ? ";
			
			ps = con.prepareStatement(sql);
			ps.setString(1, numSerial);
			if(status){
				sql += " AND t.status = 'Ativo'";
								
			}
			
			rs = ps.executeQuery();
			
			String tipoTerminal = null;
			while(rs.next()){
				tipoTerminal = rs.getString("LOCAL");
			}

			return tipoTerminal;
		}
		finally{
 			if(rs != null)
				rs.close();
			if(ps != null)
				ps.close();
			if(closeCon){
				con.close();
			}
		}
	}
}

Parte do código que chama o metodo findOperacao

try {			
			operacao = operacaoDao.findOperacao(numSerial,true);
		} catch (Exception e) {
			log.error("Erro:"+e.getMessage());
		}

		if(operacao == null )
			throw new Exception("Nao foi possivel validar a operação");

Espero que alguém possa me ajudar.
Muito Obrigado.

13 Respostas

Hebert_Coelho

Já parou para pensar que se ocorrer um erro no primeiro IF o segundo não será finalizado?

if(rs != null) rs.close(); if(ps != null) ps.close(); if(closeCon){ con.close();

W

Apesar de você ter rasão no que disse, nos meus testes isso não ocorreu.
Então penso que possa ser outra coisa. Já aconteceu com você algo parecido?

Hebert_Coelho

wagnerluis.silva:
Apesar de você ter rasão no que disse, nos meus testes isso não ocorreu.
Então penso que possa ser outra coisa. Já aconteceu com você algo parecido?
Não.
Quando eu trabalho com JDBC coloco um try/catch em cada if. Você conseguiu simular o erro corretamente em seus testes?

drsmachado

Ok, mas como foram os testes? O que ocorreu neles? Que exception é lançada e, além disto, até que ponto do finally o código é executado?

W

Ele executou todos os if contidos no finally.
Consigo verificar o erro quando ele chega no if do código que utiliza o método.

try {             
    operacao = operacaoDao.findOperacao(numSerial,true);  
} catch (Exception e) {  
    log.error("Erro:"+e.getMessage());  
}  
  
if(operacao == null )  
    throw new Exception("Nao foi possivel validar a operação");  // Acontece o erro e as sessões continuam abertas
Hebert_Coelho
wagnerluis.silva:
Ele executou todos os if contidos no finally. Consigo verificar o erro quando ele chega no if do código que utiliza o método.
try {             
    operacao = operacaoDao.findOperacao(numSerial,true);  
} catch (Exception e) {  
    log.error("Erro:"+e.getMessage());  
}  
  
if(operacao == null )  
    throw new Exception("Nao foi possivel validar a operação");  // Acontece o erro e as sessões continuam abertas
Novamente: Você consegue simular o erro em desenvolvimento?
W

Sim consigo.

neste ponto aqui que ele acontece

try {               
    operacao = operacaoDao.findOperacao(numSerial,true);    
} catch (Exception e) {    
    log.error("Erro:"+e.getMessage());    
}    
    
if(operacao == null )    
    throw new Exception("Nao foi possivel validar a operação");  // Acontece o erro e as sessões continuam abertas
Hebert_Coelho
wagnerluis.silva:
Sim consigo.

neste ponto aqui que ele acontece

try {               
    operacao = operacaoDao.findOperacao(numSerial,true);    
} catch (Exception e) {    
    log.error("Erro:"+e.getMessage());    
}    
    
if(operacao == null )    
    throw new Exception("Nao foi possivel validar a operação");  // Acontece o erro e as sessões continuam abertas
e o log.error("Erro:"+e.getMessage()); não exibe nenhuma mensagem de erro? A conexão simplesmente continua aberta?
W

Isso. A mensagem que é exibida é a do if .
E a conexão fica aberta.
Vocês conhecem alguma coisa que possa fazer com que a sessão seja liberada? Acho que isso já me ajudaria.

Gustavo_Marques

Onde fecha a conexão ele testa essa váriável booleana closeCon

if(closeCon){  
     con.close();  
}

Vá no modo debug de sua IDE e veja nessa parte se a váriavel closeCon está chegando como false;
É melhor retirar esse if e colocar direto con.close(), uma vez que no inicio do método você já testa if closed abre uma nova;

Uma estutura segura envolvendo transações é essa:

public class Dao{
   private Connection con;
   
   
   public void executaNoBanco(){
   try{
      //obtenha sua coneção this.con = ..., preferencialmente de uma classe separada
      String query = "select * from tabela";
      PreparedStatement p = con.prepareStatement();
      ResultSet rs = p.executeQuery();
      while(rs.next()){
          //guarde valores em uma lista
      }
      rs.close();
      p.close();
   }catch(Exception e){
      //log
   }finally{
      try{
         con.close();
      }catch(Exception ex){
         //log
      }
   }
   }
}

Essa estrutura foi proposta pelo livro do Deitel java como programar.

E

Se puder usar o Java 7, use isto aqui:

try (
    PreparedStatement p = con.prepareStatement();  
    ResultSet rs = p.executeQuery();  
) {
    while(rs.next()){  
        //guarde valores em uma lista  
    }  
}

que fecha as conexões e prepared statements adequadamente, se elas forem declaradas e obtidas dentro dos parênteses do try (procure por “try-with-resources”).

Aliás, a menos que você tenha um motivo muito forte, não trate “Exception” dentro de seu código em um método como esses. Trate apenas as exceções adequadas em vez de ficar pegando tudo - isso se chama “preguiça”. Quem tem de pegar tudo é uma outra parte do seu código.

Gustavo_Marques

Olá entanglement,

Com exceção de sua definição de “melhor prática”, faço minhas as suas palavras nesse post: http://www.guj.com.br/java/285902-duvida-com-metodos-estaticos

"
Muito código que posto aqui reconhecidamente não obedece às melhores práticas, a menos que eu diga explicitamente isso.

Muitas vezes eu tento escrever o código mais claro que faz uma determinada coisa - e então você vai ver certas coisas, por exemplo, como o uso de Null Layout em Swing, que não recomendo para ninguém. Ou então acessar diretamente os campos de uma classe, sem usar setters e getters. Não aconselho que as pessoas façam copy & paste do meu código, justamente porque

  • Eu uso um estilo muito peculiar, fácil de ser detectado pelos professores
  • Pretendo sempre mostrar como se faz mas não qual é a melhor prática (até porque a “melhor prática” é uma superstição inventada por aquelas pessoas que não pensam antes de fazer
    "
W

Fora esse problema com as exceções, vocês podem me dizer uma forma de “matar” as sessões que estão ficando abertas.
Preciso que elas fiquem disponíveis para outros usuários.

Criado 29 de outubro de 2012
Ultima resposta 29 de out. de 2012
Respostas 13
Participantes 5