Problema com metodo de cadastro e fechar conexão com bd

23 respostas
LostSpirit

bom estou com um probleminha
eu consgio criar o primeiro usuario, mas depois não dar pra criar mais pq estou fechando a conexão alguém poderia me dar uma ideia de como resolver isso?

public class UsuarioDAO {

    
    private Connection con;

    public UsuarioDAO() {
        this.con = new ConnectionFactory().getConnection();
    }

    public boolean add(Usuario u) {
        String sql = "INSERT INTO usuario(login,senha,administrador) VALUES(?,?,?)";
        try {
            PreparedStatement stmt = con.prepareStatement(sql);
            stmt.setString(1, u.getLogin());
            stmt.setString(2, u.getSenha());
            stmt.setBoolean(3, u.isAdm());
            stmt.execute();
            stmt.close();
            con.close();
            return true;
        } catch (SQLException ex) {
            Logger.getLogger(UsuarioDAO.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        }
    }

eu criei um construtor para que toda vez que se crie um UsuarioDAO ele tenha já conexão, se torna desnecessario?

23 Respostas

Jonathan_Medeiros

Você não precisa ficar abrindo e fechando a conexão com o BD toda vez que for fazer alguma operação, a conexão com o BD você pode iniciar junto com sua aplicação e fechá-la quando sua aplicação se encerrar.
O que você deve ter o cuidado abrir e fechar sempre em todas as operações com o seu BD são as transações.

LostSpirit

como assim transações?

Jonathan_Medeiros

Toda operação de insert, update e delete são blocos de transações com o BD, para cada uma delas deve-se ter o cuidado de abrir e fechar a transação.

Segue exemplos:
https://www.mkyong.com/jdbc/jdbc-transaction-example/
https://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html

LostSpirit

vlw vou dar uma olhada.

smatt

Exatamente! Eu, por exemplo, na classe que cria a conexão, nem crio um método para fechar a conexão. No meu método de criação, caso não exista conexão ele cria e pronto.

public static Connection getConnection() {
        try {
            if (conexao == null) {

                Class.forName(DRIVER);
                conexao = DriverManager.getConnection(URL,USER,PASS);
                statement = conexao.createStatement();
            }
            return conexao;

        } catch (ClassNotFoundException ex) {
            JOptionPane.showMessageDialog(null, "Erro no driver jdbc!");
            ex.printStackTrace();
            return null;
        } catch (SQLException ex) {
            JOptionPane.showMessageDialog(null, "Erro na conexão com o banco de dados!");
            ex.printStackTrace();
            return null;
        }
    }

Esse é o unico metodo que tem na minha classe. Dai na classe DAO eu so passo nos construtores se for necessário alguma informação para realizar algum método de transação com o BD. Talvez seja necessário ele receber uma ArrayList ou algo do tipo.

R

Prezados bom dia, desculpe a pergunta mais é uma boa pratica abrir a conexão e só ao sair do sistema fechar?

Eu dou manutenção em um sistema que usa um banco MySql na Localweb e neste sistema ( é outra linguagem ) o trabalho é abrindo e fechando a conexão se a conexão ficar aberta de bobeira por alguns instantes… da BO

Jonathan_Medeiros

Depende muito do contexto da aplicação ao qual ela se aplica, não é regra fazer isso, mas tem casos que se fazem necessário e casos que não, logo cada um implementa conforme sua necessidade.

LostSpirit

No caso seguindo a logica operações de transações seria interessante sempre fechar?

shodaime

Sim adote sempre esta boa pratica, pois isto pode gerar problemas futuros em sua aplicação.
Exemplo de uma classe de conexão que eu uso sempre
package br.com.appteste.connection;

import br.com.appteste.util.ConstantesBanco;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.swing.JOptionPane;

/**
*
*
*/
public class Conexao {

public Connection con;

static String host = ConstantesBanco.HOST_LOCAL;
static String database = ConstantesBanco.DATABASE;
static String usuario = ConstantesBanco.USUARIO;
static String senha = ConstantesBanco.SENHA;
static String url = ConstantesBanco.URL_LOCAL;


public Conexao() {

    conectar(); //chamando o metodo conectar

}

public void conectar() {
    try {
        Class.forName("org.postgresql.Driver");
        System.out.println("Driver OK!!!");

        con = DriverManager.getConnection(url, usuario, senha);
        System.out.println("Conexão OK!!!");

    } catch (ClassNotFoundException exc) {
       
        System.out.println("Erro no driver, ClassNotFoundException " + exc.getMessage());

    } catch (SQLException exc) {
        System.out.println("Erro de conexao ,SQLException " + exc.getMessage());
        //JOptionPane.showMessageDialog(null, "Erro ao conectar no Banco de Dados! \n"+exc.getMessage(),"Erro ao Conectar no Banco de Dados",JOptionPane.ERROR_MESSAGE);
    }
}

public void fecharConexao() {
    try {
        con.close(); // fechando a conexao
        System.out.println("CONEXÃO FECHADA!");
    } catch (SQLException exc) {
        System.out.println(exc.getMessage());
        //JOptionPane.showMessageDialog(null, "Erro ao fechar Conexão  no Banco de Dados! \n"+exc.getMessage(),"Erro ao Fechar  Banco de Dados",JOptionPane.ERROR_MESSAGE);
    }
}

}

LostSpirit

man me tira só uma dúvida em relação a url
“jdbc:mysql://localhost:3306/xxx”
teria como por algo menor do q isso? ou tem que ser exatamente assim…

shodaime

seria isto mesmo

Jonathan_Medeiros

As transações sim, a conexão com o BD somente se você julgar necessário!

LostSpirit

Ou seja um ex válido o login no método de validação onde tem a transação select eu fecharia e ao fazer login eu abriria novamente ?
Ou fechar apenas o preparedstatment?

Jonathan_Medeiros

Consultas não são transacionais, pois as mesmas não alteram o estado atual dos dados.
Somente instruções de inserção, alteração e deleção são transacionais, pois as mesmas modificam o estado atual dos dados.

Sobre seu código você pode fechar somente o PreparedStatement.

LostSpirit

Fechando somente o prepared não irá fechar a conexão não é?
Caso eu faça um insert fechar apenas o prepared iria resolver ?

Jonathan_Medeiros

Sim, são objetos distintos, fechar o pst não influencia na conexão.

Isso aqui ficou um pouco confuso, resolver o que exatamente?

LostSpirit

Sobre abrir transacoes, fechar só com preparares já resolve? Ou é necessário fechar a conexão?

Jonathan_Medeiros

A conexão não precisa ser fechada, a não ser que você queira manter esse padrão de abrir e fechar a conexão sempre, mas tem que ter o cuidado e a atenção para garantir que a conexão esteja ativa sempre que for fazer qualquer operação relacionada com o BD, como um CRUD por exemplo.
A parte de transações vai um pouco além do que foi comentado aqui, elas incidem diretamente ao uso de commit e rollback visando sempre as propriedades ACID.
O PreparedStatement é só uma classe que nos fornece meios de fazer esse controle, mas é preciso todo o entendimento real por trás disso tudo para que não se faça algo errado.
Ou seja só o fato de dar o close no objeto não diz respeito a transação, pegou mais ou menos a ideia?

LostSpirit

Vou dar uma procurada sobre commit e rollback, peguei sim, vou dar uma lida para tentar fazer o Max possível no padrão, vlw man.

LostSpirit

Se você poder me dar um exemplo de como eu usaria o commit e rollback no Java para tentar compreender, tava dando uma olhada e falam que tem que comitar todas as transações de uma vez kk, o problema é que tenho muitos métodos, se você poder ajudar com algum exemplo com mais de um método .

LostSpirit

Dando uma aprofundada percebi que nao necessariamente necessita commitar tudo de uma única vez e sim o máximo possível,
Poderia me corrigir se eu estiver errado?
Nesse caso não seria necessário commitar o select
E se eu fizer um select e depois um update eu teria que executar o select normalmente e depois commitar o update ?
Ou no caso fazer um método isolado para o update e chamar no método de insert?
Estou na lógica certa?

Ficaria grato se poder me dar um exemplo de commite utilizando mais de um método.

Jonathan_Medeiros

Commit se aplica sempre à uma transação completa, nunca parcial.

Não entendi sua pergunta, select é consulta, e consulta não envolve o âmbito de transações.

Está muito confuso, porquê fazer um método de update em um método de insert?!

Um exemplo de transação que você utilizaria múltiplos métodos, seria uma venda por exemplo.

Início da transação

  • Insere a venda
  • Insere os ítens da venda
  • Insere a baixa do estoque
  • Insere o contas a receber
  • Insere o movimento de caixa

Fim da transação

Se todas etapas foram concluídas com sucesso então é aplicado o commit na transação, caso contrário alguma etapa apresente falha então é aplicado o rollback.

LostSpirit

Pq eu tenho um campo no usuário , como ativo, boolean para verificar se ele está online,
Seria um alter table na verdd, falando nisso você poderia me ajudar se tem como chamar um método ao fechar o app, (ex se fechar instância pelo gerenciador chamasse esse método tambrm, para alterar o campo para 0)
Eu teria que trabalhar com rotina no caso ?

Criado 19 de junho de 2019
Ultima resposta 24 de jun. de 2019
Respostas 23
Participantes 5