[JAVA/JDBC] Como abrir duas conexões com o mesmo banco no mesmo método?

A pergunta é um pouco confusa, mas o problema é literalmente esse.

No meu projeto JavaWeb, trabalho com DAO, e possuo um metodo que faz uma busca no banco buscando os dados de uma determinada tabela, e quando estou recuperando os valores do resultset, jogando pra dentro de um objeto, tenho a necessidade de chamar um outro método (passando como parâmetros alguns valores do resultado do resultset) este método retorna um valor na qual eu seto para um atributo desse objeto.

O problema é que quando vai executar esse método, ao tentar abrir uma nova conexão com o banco, a conexão que estava antes é perdida e por consequência essa nova nem sequer é aberta
ERRO: java.sql.SQLException: You can’t operate on a closed Connection!!!

OBS.: Ja tentei passar a conexão como parâmetro, mas da na mesma

Código
public Collection geraRelContraCheque(int idRecibo) {
        Vector v = new Vector();

        ResultSet rs = null;
        PreparedStatement pstmt = null;
        ConexaoBanco conn = new ConexaoBanco();

        String sql = " SELECT o.nome AS nome_orgao, " +
                     "      o.cnpj, o.codigo AS codigo_orgao, " +
                     "      r.mes, r.ano, o.logotipo as logotipo, " +
                     "      r.tipo, c.nome AS nomeCargo, c2.nome AS nomeCargoOriginal, " +
                     "      s.nome AS nomesecao, " +
                     "      b.codigo || ' - ' || b.nome AS banco, " +
                     "      p.cpf, f.matricula, f.ehConcursado, f.dataPosse, " +
                     "      p.nome AS nomep, c.cbo, " +
                     "      p.nascfundacao, r.valorliquido AS liquido, " +
                     "      r.valordescontos AS totaldesc, r.valorproventos, " +
                     "      t.descricao AS nometipofolha, rhvinculos.dataadmissao, " +
                     "      rhvinculosddm.cccontabancaria, rhvinculosddm.salario, " +
                     "      rhvinculosddm.secao, tipoAdPub.descricao AS tipoAdmissaoNome " +
                     " FROM recibos r " +
                     " LEFT JOIN rhvinculos ON rhvinculos.id = r.idvinculo " +
                     " JOIN funcionarios f ON rhvinculos.funcionario = f.matricula " +
                     " LEFT JOIN tipo_admissao_publico tipoAdPub ON tipoAdPub.codigo = rhvinculos.tipoadmissaopublico " +
                     " INNER JOIN rhvinculosddm ON rhvinculosddm.idvinculo = rhvinculos.id AND " +
                     "      rhvinculosddm.ano = r.ano AND " +
                     "      rhvinculosddm.mes = r.mes " +
                     " LEFT JOIN orgaos o ON o.codigo = rhvinculos.orgaoregistrotribunal " +
                     " LEFT JOIN cargos c ON rhvinculosddm.codigocargo = c.codigo " +
                     " LEFT JOIN cargos c2 ON f.cargoAdmissao = c2.codigo " +
                     " LEFT JOIN secoes s ON rhvinculosddm.secao = s.id " +
                     " LEFT JOIN agencias_bancarias ab ON rhvinculosddm.cccontabancaria = ab.id " +
                     " LEFT JOIN bancos b ON ab.banco = b.codigo " +
                     " LEFT JOIN pessoas p ON f.codigopessoa = p.codigo " +
                     " LEFT JOIN tipos_folhas t ON r.tipo = t.codigo where r.id = ?";

        try {
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, idRecibo);
            
            
            rs = pstmt.executeQuery();

            if (rs.next()) {

                Rel_ContraCheque rel = new Rel_ContraCheque();

                rel.setId(idRecibo);

                rel.setNomeOrgao(rs.getString("nome_orgao"));
                rel.setTipoAdmissaoNome(rs.getString("tipoAdmissaoNome"));
                rel.setCodigoOrgao(rs.getInt("codigo_orgao"));
                rel.setInscricaoOrgao(rs.getString("cnpj"));
                rel.setNomeCargo(rs.getString("nomeCargo"));
                rel.setNomeCargoOriginal(rs.getString("nomeCargoOriginal"));
                rel.setNomeSecao(rs.getString("nomeSecao"));
                rel.setDataPosse(rs.getDate("dataPosse"));

                if (rs.getInt("tipo") == 1) {
                    rel.setRefStr(UteisData.getMonth(rs.getInt("mes")) + "/" + rs.getInt("ano"));
                } else {
                    rel.setRefStr(rs.getString("nometipofolha") + " " + UteisData.getMonth(rs.getInt("mes")) + "/" + rs.getInt("ano"));
                }
                
                if (rs.getString("ehConcursado").equals("S")){
                    rel.setNomeDataPosse("Data da Posse: " + new Uteis().constStr("\u00A0", 10) + UteisData.converteData(rel.getDataPosse(), UteisData.FormatData.DATA_SIMPLES));
                }else{
                    rel.setNomeDataPosse("");
                }
                

                rel.setBanco(rs.getString("banco"));
                rel.setConta(rs.getString("CCcontaBancaria"));
                rel.setCpf(rs.getString("cpf"));
                rel.setDtAdmissao(rs.getDate("dataadmissao"));
                rel.setMatricula(rs.getInt("matricula"));
                rel.setNome(rs.getString("nomep"));
                rel.setCbo(rs.getString("cbo"));
                rel.setSecao(rs.getString("secao"));
                rel.setDataNascFundacao(rs.getDate("nascfundacao"));
                rel.setLiquido(rs.getDouble("liquido"));
                rel.setTotalDesc(rs.getDouble("totalDesc"));
                rel.setTotalVenc(rs.getDouble("valorproventos"));
                rel.setSalBase(rs.getDouble("salario"));
                rel.setMes(rs.getInt("mes"));

              
                Integer orgao = rs.getInt("codigo_orgao");
                Date dataNascimento = rs.getDate("nascfundacao");
                Integer mes = rs.getInt("mes");
                
                
                  Blob blob = rs.getBlob("logotipo");
                if (blob != null) {
                    byte[] bin = blob.getBytes(1, (int) blob.length());
                    ByteArrayInputStream stream = new ByteArrayInputStream(bin);
                    rel.setLogotipo(stream);
                }
                

                rel.setMensagem(this.getInfoMensagem(dataNascimento, mes,conn));

                **//CHAMADA DO METODO QUE CAUSA O PROBLEMA**
                rel.setMargemConsignavel(this.calculaMargemConsignavel(idRecibo, rel.getTotalVenc(), conn));

                v.add(rel);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            UteisDataBase.liberarRecursosBD(rs, pstmt, conn);
        }

        return v;
    }

[/details][details=Método que causa o problema]
public Double calculaMargemConsignavel(Integer idRecibo, Double salarioBruto, ConexaoBanco conn) {

        Double resposta = null;
        Double margemJaConsignada = null;
        Double margemQueAindaPodeSerConsignada = null;
        Double margemConsignavel = null;
        Double valorMaximoConsignavel = null;

        ResultSet rs = null;
        String sql = "";
        PreparedStatement pstmt = new PreparedStatement();

        sql = "SELECT pf.margemConsignavel "
                + " from PARAMETROS_FOLHA PF";

        try {

            pstmt = conn.prepareStatement(sql);

            rs = pstmt.executeQuery();

            if (rs.next()) {

                margemConsignavel = rs.getDouble("margemConsignavel");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            UteisDataBase.liberarRecursosBD(rs, pstmt);
        }

        valorMaximoConsignavel = salarioBruto * margemConsignavel / 100;

        sql = "select sum(re.valor) as valor "
                + " from eventos e, RECIBOS_EVENTOS RE "
                + " where e.tipodesconto = 3  and  RE.CODIGOEVENTO=E.CODIGO and re.idrecibo = ?";

        try {

            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, idRecibo);

            rs = pstmt.executeQuery();

            if (rs.next()) {

                margemJaConsignada = rs.getDouble("valor");
                margemQueAindaPodeSerConsignada = valorMaximoConsignavel - margemJaConsignada;
                resposta = margemQueAindaPodeSerConsignada;

            }
            return resposta;
        } catch (Exception e) {
            e.printStackTrace();
            return resposta;
        } finally {
            UteisDataBase.liberarRecursosBD(rs, pstmt);
        }

    }

Se puderem me dar uma luz, ficarei grato

Não sei se ajuda, mas veja que eu sempre abro uma conexão, linha 19 e sempre encerro ela, linha 29.

1. public class ContDao {

2.     private static Connection conn;
3.     private static PreparedStatement ps;
4.     private static ResultSet rs;
5.     private static StringBuilder SQL;
6. /**
7.  * Lista todos os registros
8.  * @param codigo
9.  * @return 
10.  */ public static List <ContMod> listaDados (String codigo) {
11.         List <ContMod> lista = new ArrayList();
12.         ContMod obj;
13.         if (codigo.isEmpty()){
14.             SQL = new StringBuilder("select * from aux_continente order by descr");
15.         } else {
16.             SQL = new StringBuilder("select * from aux_continente where codcont = '"+codigo+"'");
17.         }            
18.         try {
19.             conn = Conn.getConnection();
20.             ps = conn.prepareStatement(SQL.toString());
21.             rs = ps.executeQuery();
22.             while(rs.next()){
23.                 obj = new ContMod(rs.getString("codcont"),rs.getString("descr"),"");
24.                 lista.add(obj);
25.             }
26.         } catch (Exception e) {
27.             Util.mensagem("Error (Lista): "+e.getMessage());
28.         } finally {
29.             Conn.closeConnection(conn, ps, rs);
30.         }        
31.         return lista;
32.     }
33. }

Outra coisa: Mesmo chamando a minha conexão eu verifico se ela esta aberta.

1. package conn;

2. import java.sql.Connection;
3. import java.sql.DriverManager;
4. import java.sql.PreparedStatement;
5. import java.sql.ResultSet;
6. import java.sql.SQLException;
7. import util.Util;
8. /**
9.  * Classe de conexão com banco de dados
10.  * @author vonquelbe.caldeira
11.  */
12. public class Conn {
13.     public  static Connection conn = null;
14.     private static String url   = "jdbc:mysql://localhost:3306/server";
15.     private static String login = "Login";
16.     private static String senha = "Senha";
17. /**
18.  * Método de conexão com banco e tem como retorno um Connection
19.  * @return 
20.  */ public static Connection getConnection() {
21.         try {
22.             if (conn == null) {
23.                 Class.forName("com.mysql.jdbc.Driver");
24.                 conn = DriverManager.getConnection(url, login, senha);
25.             } else {
26.                 if (conn.isClosed()) {
27.                     Class.forName("com.mysql.jdbc.Driver");
28.                     conn = DriverManager.getConnection(url, login, senha);
29.                 }
30.             }
31.         } catch (Exception ex) {
32.             Util.mensagem("Erro ao conectar: " + ex.getMessage());
33.         }
34.         return conn;
35.     }
36. /**
37.  * Encerra conexão
38.  */ public static void closeConnection (){
39.         try {
40.             if(!conn.isClosed() ){
41.                 conn = null;
42.             }
43.         } catch (SQLException ex){
44.             Util.mensagem("Erro ao encerrar conexão: "+ex.getMessage());
45.         }
46.     } 
47. /**
48.  * Encerra concexão passando conexão como parâmetro
49.  * @param conn Tipo Connection
50.  */ public static void closeConnection (Connection conn){
51.         try {
52.             if(!conn.isClosed() ){
53.                 conn = null;
54.             }
55.         } catch (SQLException ex){
56.             Util.mensagem("Erro ao encerrar conexão: "+ex.getMessage());
57.         }
58.     }
59. /**
60.  * Encerra conexão e Statement
61.  * @param conn Tipo Connection
62.  * @param ps Tipo PreparedStatement
63.  */ public static void closeConnection (Connection conn, PreparedStatement ps){
64.         closeConnection(conn);
65.         try {
66.             if(!ps.isClosed()) {
67.                 ps.close();
68.             }
69.         } catch (Exception e) {
70.             Util.mensagem("Erro ao encerrar Statement: "+ e.getMessage());
71.         }
72.     } 
73. /**
74.  * Encerra conexão, Statement e ResultSet
75.  * @param conn Tipo Connection
76.  * @param ps Tipo PreparedStatement
77.  * @param rs Tipo ResultSet
78.  */ public static void closeConnection (Connection conn, PreparedStatement ps, ResultSet rs){
79.         closeConnection(conn, ps);
80.         try {
81.             if(!rs.isClosed()) {
82.                 rs.close();
83.             }
84.         } catch (Exception e) {
85.             Util.mensagem("Erro ao encerrar ResultSet: "+ e.getMessage());
86.         }
87.     } 
88. /**
89.  * Classe para encerramento do sistem fechando a conexão
90.  */ public static void closeSystem (){
91.         closeConnection();
92.         Util.mensagem("Sessão encerrada ...");
93.         System.exit(0);
94.     }    
95. }

Espero ter ajudado.

Não vejo motivo para ficar abrindo e fechando a conexão.
Enquanto o usuário de seu sistema estiver conectado, mantenha a conexão com a base de dados.

3 curtidas

Em todo meu sistema, eu trabalho sobre aquela ideia de abrir uma conexão, solicitar um serviço ao banco e quando este terminar eu fecho essa conexão, pois assim eu evito que a aplicação consuma meu servidor sem necessidade. Quer dizer que estou errado?

Em um sistema grande, ficar abrindo e fechando conexões pode se tornar um bottleneck, muito cuidado com isso. Nessas ocasiões é mais usado uma pool de conexões constantemente abertas, que são “recicladas” entre as threads por requisição.

Mesmo em um sistema pequeno, usar uma pool de conexões (mesmo que pequena) é mais interessante, na minha opinião. O overhead de ficar abrindo e fechando conexões pode ser pior do que deixar conexões abertas.

Parti do mesmo principio do @Augusto_Soares8. Mas no meu modelo seria penas retirar o Conn.closeConnection(conn, ps, rs) da linha 29, certo ? Já que quando tento conectar ele verifica se já não esta conectado.

Eu utilizo em meu sistema um pool de conexões(c3p0), esse metodo liberarRecursosBD() não fecha a conexão de fato como no jdbc puro, mas ela é devolvida ao pool de conexao (DataSource), para que esse faço o seu gerenciamento.

O meu problema é que necessito executar essa primeira query com a seguinte conexão, pegar os resultados (resultSet) e chamar outro metodo passando como parametro essa mesma conexão e alguns valores desse resultado, e depois executar outra query que ira me retornar um valor…

Encontrei a resposta ao ler a documentação, mas não é uma solução:

By default, only one ResultSet object per Statement object can be open at the same time. Therefore, if the reading of one ResultSet object is interleaved with the reading of another, each must have been generated by different Statement objects. All execution methods in the Statement interface implicitly close a statment’s current ResultSet object if an open one exists.

Para cada Statement só pode ter aberto um ResultSet. Terei que repensar essa rotina…
Obrigado pelas respostas.

Coloque o código desse método que libera os recursos. Muito provavelmente você está fechando a conexão dentro dele também.

[details=liberarRecursosBD()]
public static void liberarRecursosBD(ResultSet rs, PreparedStatement ps, ConexaoBanco conn) {
try {
if (conn != null) {
conn.setAutoCommit(true);
}
if (rs != null) {
rs.close();
}
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException sqle) {
sqle.printStackTrace(System.out);
} catch (Exception e) {
e.printStackTrace(System.out);
}
}[/details]

Eu fiz alguma alterações momentâneas para o cliente conseguir imprimir os contra-cheques… Porem ele só conseguira imprimir um por vez, a minha intenção era que se ele quisesse, poderia imprimir uma lista de contra-cheques, mas como disse tenho que repensar melhor isso, mas por agora o que fiz foi:

  • O método que causava o problema, recebe os seus parâmetros normais e o ResultSet, Statement e a Conexão
  • O método executa a query e simplesmente retorna o valor, sem fechar a conexão
  • E ai sim no método pai, a conexão é encerrada.

Ficou dessa forma /

Método pai
    public Collection geraRelContraCheque(int idRecibo) {
        List<Rel_ContraCheque> lista = new ArrayList<>();

        ResultSet rs = null;
        PreparedStatement pstmt = null;
        ConexaoBanco conn = new ConexaoBanco();

        String sql = " SELECT o.nome AS nome_orgao, " +
                     "      o.cnpj, o.codigo AS codigo_orgao, " +
                     "      r.mes, r.ano, o.logotipo, " +
                     "      r.tipo, c.nome AS nomeCargo, c2.nome AS nomeCargoOriginal, " +
                     "      s.nome AS nomesecao, " +
                     "      b.codigo || ' - ' || b.nome AS banco, " +
                     "      p.cpf, f.matricula, f.ehConcursado, f.dataPosse, " +
                     "      p.nome AS nomep, c.cbo, " +
                     "      p.nascfundacao, r.valorliquido AS liquido, " +
                     "      r.valordescontos AS totaldesc, r.valorproventos, " +
                     "      t.descricao AS nometipofolha, rhvinculos.dataadmissao, " +
                     "      rhvinculosddm.cccontabancaria, rhvinculosddm.salario, " +
                     "      rhvinculosddm.secao, tipoAdPub.descricao AS tipoAdmissaoNome " +
                     " FROM recibos r " +
                     " LEFT JOIN rhvinculos ON rhvinculos.id = r.idvinculo " +
                     " JOIN funcionarios f ON rhvinculos.funcionario = f.matricula " +
                     " LEFT JOIN tipo_admissao_publico tipoAdPub ON tipoAdPub.codigo = rhvinculos.tipoadmissaopublico " +
                     " INNER JOIN rhvinculosddm ON rhvinculosddm.idvinculo = rhvinculos.id AND " +
                     "      rhvinculosddm.ano = r.ano AND " +
                     "      rhvinculosddm.mes = r.mes " +
                     " LEFT JOIN orgaos o ON o.codigo = rhvinculos.orgaoregistrotribunal " +
                     " LEFT JOIN cargos c ON rhvinculosddm.codigocargo = c.codigo " +
                     " LEFT JOIN cargos c2 ON f.cargoAdmissao = c2.codigo " +
                     " LEFT JOIN secoes s ON rhvinculosddm.secao = s.id " +
                     " LEFT JOIN agencias_bancarias ab ON rhvinculosddm.cccontabancaria = ab.id " +
                     " LEFT JOIN bancos b ON ab.banco = b.codigo " +
                     " LEFT JOIN pessoas p ON f.codigopessoa = p.codigo " +
                     " LEFT JOIN tipos_folhas t ON r.tipo = t.codigo where r.id = ?";

        try {
            conn.setAutoCommit(false);
            pstmt = conn.prepareStatement(sql);
            pstmt.setValue(idRecibo);
            
            rs = pstmt.executeQuery();

            while (rs.next()) {
                Rel_ContraCheque rel = new Rel_ContraCheque();

                rel.setId(idRecibo);

                rel.setNomeOrgao(rs.getString("nome_orgao"));
                rel.setTipoAdmissaoNome(rs.getString("tipoAdmissaoNome"));
                rel.setCodigoOrgao(rs.getInt("codigo_orgao"));
                rel.setInscricaoOrgao(rs.getString("cnpj"));
                rel.setNomeCargo(rs.getString("nomeCargo"));
                rel.setNomeCargoOriginal(rs.getString("nomeCargoOriginal"));
                rel.setNomeSecao(rs.getString("nomeSecao"));
                rel.setDataPosse(rs.getDate("dataPosse"));

                if (rs.getInt("tipo") == 1) {
                    rel.setRefStr(UteisData.getMonth(rs.getInt("mes")) + "/" + rs.getInt("ano"));
                } else {
                    rel.setRefStr(rs.getString("nometipofolha") + " " + UteisData.getMonth(rs.getInt("mes")) + "/" + rs.getInt("ano"));
                }
                
                if (rs.getString("ehConcursado").equals("S")){
                    rel.setNomeDataPosse("Data da Posse: " + new Uteis().constStr("\u00A0", 10) + UteisData.converteData(rel.getDataPosse(), UteisData.FormatData.DATA_SIMPLES));
                }else{
                    rel.setNomeDataPosse("");
                }

                rel.setBanco(rs.getString("banco"));
                rel.setConta(rs.getString("CCcontaBancaria"));
                rel.setCpf(rs.getString("cpf"));
                rel.setDtAdmissao(rs.getDate("dataadmissao"));
                rel.setMatricula(rs.getInt("matricula"));
                rel.setNome(rs.getString("nomep"));
                rel.setCbo(rs.getString("cbo"));
                rel.setSecao(rs.getString("secao"));
                rel.setDataNascFundacao(rs.getDate("nascfundacao"));
                rel.setLiquido(rs.getDouble("liquido"));
                rel.setTotalDesc(rs.getDouble("totalDesc"));
                rel.setTotalVenc(rs.getDouble("valorproventos"));
                rel.setSalBase(rs.getDouble("salario"));
                rel.setMes(rs.getInt("mes"));

                // é necessário pegar os valores do resultSet antes de chamar os métodos porque o resultSet será fechado pelos mesmos
                // especificacao JDBC
                Integer orgao = rs.getInt("codigo_orgao");
                Date dataNascimento = rs.getDate("nascfundacao");
                Integer mes = rs.getInt("mes");
                
                
                Blob blob = rs.getBlob("logotipo");
                if (blob != null) {
                    byte[] bin = blob.getBytes(1, (int) blob.length());
                    ByteArrayInputStream stream = new ByteArrayInputStream(bin);
                    rel.setLogotipo(stream);
                }
                

                rel.setMensagem(this.getInfoMensagem(dataNascimento, mes,conn));
                
                
//                rel.setLogotipo(this.carregaLogotipo(orgao,conn));

                //MÉTODO QUE CAUSAVA PROBLEMA
                rel.setMargemConsignavel(this.calculaMargemConsignavel(idRecibo, rel.getTotalVenc(), conn, pstmt, rs));

                lista.add(rel);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
             try {
                conn.setAutoCommit(false);
            } catch (Exception e) {
                e.printStackTrace();
            }
            UteisDataBase.liberarRecursosBD(rs, pstmt, conn);
        }

        return lista;
    }
Método filho
 public Double calculaMargemConsignavel(Integer idRecibo, Double salarioBruto, ConexaoBanco conn, PreparedStatement pstmt, ResultSet rs) {

        Double resposta = null;
        Double margemJaConsignada = null;
        Double margemQueAindaPodeSerConsignada = null;
        Double margemConsignavel = null;
        Double valorMaximoConsignavel = null;

        String sql = "";

        sql = "SELECT pf.margemConsignavel "
                + " from PARAMETROS_FOLHA PF";

        try {

            pstmt = conn.prepareStatement(sql);

            rs = pstmt.executeQuery();

            if (rs.next()) {

                margemConsignavel = rs.getDouble("margemConsignavel");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } 

        valorMaximoConsignavel = salarioBruto * margemConsignavel / 100;

        sql = "select sum(re.valor) as valor "
                + " from eventos e, RECIBOS_EVENTOS RE "
                + " where e.tipodesconto = 3  and  RE.CODIGOEVENTO=E.CODIGO and re.idrecibo = ?";

        try {
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, idRecibo);

            rs = pstmt.executeQuery();

            if (rs.next()) {

                margemJaConsignada = rs.getDouble("valor");
                margemQueAindaPodeSerConsignada = valorMaximoConsignavel - margemJaConsignada;
                resposta = margemQueAindaPodeSerConsignada;

            }
            return resposta;
        } catch (Exception e) {
            e.printStackTrace();
            return resposta;
        } 

    }

Então @Augusto_Soares8 segundo a dica do @staroski eu alterei meu método para persistir a conexão enquanto o usuário estiver conectado, mas como recuperar a conexão ? Bem, veja como ficou a minha classe de conexão:

1.     package util;

2.     import java.sql.Connection;
3.     import java.sql.DriverManager;
4.     import java.sql.PreparedStatement;
5.     import java.sql.ResultSet;
6.     import java.sql.SQLException;
7.     /**
8.      * Classe de conexão com banco de dados
9.      * @author vonquelbe.caldeira
10.      */
11.     public class Conn {
12.         public  static Connection conn = null;
13.         private static String url   = "jdbc:mysql://localhost:3306/server";
14.         private static String login = "Login";
15.         private static String senha = "Senha";
16.     //  Variável estática que conterá a instancia da classe
17.         private static Conn instance;
18.     /**
19.      * Método de conexão com banco e tem como retorno um Connection
20.      * @return 
21.      */ public static Connection getConnection() {
22.             try {
23.                 if (conn == null) {
24.                     Class.forName("com.mysql.jdbc.Driver");
25.                     conn = DriverManager.getConnection(url, login, senha);
26.                 } else {
27.                     if (conn.isClosed()) {
28.                         Class.forName("com.mysql.jdbc.Driver");
29.                         conn = DriverManager.getConnection(url, login, senha);
30.                     }
31.                 }
32.             } catch (Exception ex) {
33.                 Util.mensagem("Erro ao conectar: " + ex.getMessage());
34.             }
35.             return conn;
36.         }
37.     //  Método público estático de acesso único ao objeto!
38.     //  Conn con = Conn.getInstance();
39.         public static Conn getInstance() {
40.             if (instance == null) {
41.                 instance = new Conn();
42.             }
43.             return instance;
44.         }
45.     /**
46.      * Encerra conexão
47.      */ public static void closeConnection (){
48.             try {
49.                 if(!conn.isClosed() ){
50.                     conn.close();
51.                 }
52.             } catch (SQLException ex){
53.                 Util.mensagem("Erro ao encerrar conexão: "+ex.getMessage());
54.             }
55.         } 
56.     /**
57.      * Encerra Statement
58.      * @param rs Tipo ResultSet
59.      */ public static void closeConnection (PreparedStatement ps){
60.             try {
61.                 if(!ps.isClosed()) {
62.                     ps.close();
63.                 }
64.             } catch (Exception e) {
65.                 Util.mensagem("Erro ao encerrar Statement: "+ e.getMessage());
66.             }
67.         } 
68.     /**
69.      * Encerra Statement e ResultSet
70.      * @param ps Tipo PreparedStatement
71.      * @param rs Tipo ResultSet
72.      */ public static void closeConnection (PreparedStatement ps, ResultSet rs){
73.             closeConnection(ps);
74.             try {
75.                 if(!rs.isClosed()) {
76.                     rs.close();
77.                 }
78.             } catch (Exception e) {
79.                 Util.mensagem("Erro ao encerrar ResultSet: "+ e.getMessage());
80.             }
81.         } 
82.      /**
83.      * Classe para encerramento do sistem fechando a conexão
84.      */ public static void closeSystem (){
85.             closeConnection();
86.             Util.mensagem("Sessão encerrada ...");
87.             System.exit(0);
88.         }
89.     }

O que mudou ?

  • Criei um objeto com o nome “instance” do tipo da minha Classe “Conn”, linha 17.
  • Criei um método para recuperar a minha classe, linha 39 à 44.

Então, agora, quando o usuário se loga no sistema eu chamo meu método de conexão, linha 21.
Esse método é a primeira coisa que faço, antes mesmo do usuário informar Login e Senha pois se o Banco não esta no ar ou se der algum problema na conexão ele já da mensagem de erro, linha 33.

Alterei, também, todos os meus DAO´s para recuperarem a minha classe de conexão e assim o meu objeto de conexão. Veja como ficou a minha classe ContDao:

1. package modao;

2. import java.sql.PreparedStatement;
3. import java.sql.ResultSet;
4. import util.Conn;
5. import java.util.ArrayList;
6. import java.util.List;
7. import util.Util;
8. /**
9.  * Classe DAO da tabela aux_continente
10.  * @author vonquelbe.caldeira
11.  */
12. public class ContDao {

13.     private static PreparedStatement ps;
14.     private static ResultSet rs;
15.     private static StringBuilder SQL;
16. /**
17.  * Lista todos os registros
18.  * @param codigo
19.  * @return 
20.  */ public static List <ContMod> listaDados (String codigo) {
21.         List <ContMod> lista = new ArrayList();
22.         ContMod obj;
23.         if (codigo.isEmpty()){
24.             SQL = new StringBuilder("select * from aux_continente order by descr");
25.         } else {
26.             SQL = new StringBuilder("select * from aux_continente where codcont = '"+codigo+"'");
27.         }            
28.         try {
29.             Conn cnx = Conn.getInstance();
30.             ps = cnx.conn.prepareStatement(SQL.toString());
31.             rs = ps.executeQuery();
32.             while(rs.next()){
33.                 obj = new ContMod(rs.getString("codcont"),rs.getString("descr"),"");
34.                 lista.add(obj);
35.             }
36.         } catch (Exception e) {
37.             Util.mensagem("Error (Lista): "+e.getMessage());
38.         } finally {
39.             Conn.closeConnection(ps, rs);
40.         }        
41.         return lista;
42.     }
43. }

Veja como recupero a minha classe na linha 29 e como instancio o Statement na linha 30. Agora na linha 39 eu encerro apenas o PreparedStatement e o ResultSet.

Nos métodos que uso apenas o PreparedStatement eu encerro apenas ele: Conn.closeConnection(ps);

Em que momento eu encerro a conexão agora ? Quando o usuário encerra a aplicação eu chamo o método closeSystem da minha classe de conexão que encerra a conexão, exibe mensagem e fecha a aplicação.