Dados não atualizados na aplicação

Bom dia Colegas !

Meu problema é o seguinte, tenho uma aplicação swing que acessa um banco de dados MySql, até ai tudo bem.
Só que quando eu tenho a aplicação rodando em duas máquinas e faço uma alteração em algum dado em uma delas não aparece na outra máquina, a menos que eu feche a aplicação e abra de novo !

Alguem sabe o que pode estar errado ?

Pensei que o problema fosse na classe que gera a conexão com o banco… ai vai o código dessa classe:

/*
 * ConnectionFactory.java
 *
 * Created on 28 de Maio de 2007, 17:33
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package com.atm.DAO;

import atm.*;
import java.sql.*;
import javax.swing.JOptionPane;

/**
 *
 * @author r100320
 */
public class ConnectionFactory {        
    private static ConnectionFactory instanciaUnica = null;
    private Connection conn = null;    
    private static int clientes = 0;
    
    /** Creates a new instance of ConnectionFactory */
    private ConnectionFactory(){
        try {
                //Conexão MySql 
                
                Class.forName("com.mysql.jdbc.Driver");
                System.out.println("Conectando ao banco MySql...");
                conn = DriverManager.getConnection("jdbc:mysql://localhost/atmDB",
                                                "root","D78_hc121");   
                
                conn.setAutoCommit(false);
                System.out.println("Conectado ao banco MySql...");
                                   

        } catch (ClassNotFoundException e){
                JOptionPane.showMessageDialog(null,"Falha na conexão com o banco de dados \n" + e.getMessage()) ;
                e.printStackTrace();
        } catch (SQLException e ) {
                JOptionPane.showMessageDialog(null,"Falha na conexão com o banco de dados \n" + e.getMessage()) ;
                e.printStackTrace();
        }
    } 
    
    public static ConnectionFactory getInstance(){
        if (instanciaUnica == null) {
            instanciaUnica = new ConnectionFactory();                 
        } 
        return instanciaUnica;
    }
    
    public Connection getConnection(){
        if (conn == null){
            throw new RuntimeException("Conexão nula");
        }
        clientes++;
        System.out.println("Conexão " + clientes);
        return conn;        
    }
    
    public void shutDown(){
        System.out.println("Shutdown " + clientes);
        clientes--;
        if (clientes > 0) 
            return;
        
        try {
            conn.close();
            instanciaUnica = null;
            System.out.println("Conexão fechada");
            conn = null;
        } catch (SQLException sqle) {
            System.out.println(sqle);
        }
    }
}

Caso alguém possa me ajudar ficarei muito agradecido !

Abraços.

Se você deu este comando:

                conn.setAutoCommit(false);  

isto quer dizer que para efetivar suas alterações você precisa explicitamente dar um “commit” (ou via SQL, ou via método commit da interface Connection - veja a documentação em javadoc: commit

Bom dia Colegas !

thingol:

Primeiro obrigado pela resposta.
Mas infelizemente eu já estou colocando o comando de commit.
Veja o código de um método que faz atualização de uma tabela:


    public void atualizaEquipamentoSistema(EquipamentoSistema equipamentoSistema){
        try {
            conn = ConnectionFactory.getInstance().getConnection();
            stp = conn.prepareStatement("Update equipamentosistema set ec_eqIdEquipamento = ?,  " +
                                        "ec_coIdCondominio = ?, " +
                                        "ec_ecLocalizacao = ?, " +
                                        "ec_ecNomeSistema = ? " +
                                        "where ec_ecIdSistema = ?") ;
            
            stp.setInt(1,equipamentoSistema.getEquipamento().getEqeqIdEquipamento());
            stp.setInt(2,equipamentoSistema.getCondominio().getIdCondominio());
            stp.setString(3,equipamentoSistema.getLocalizacao());
            stp.setString(4,equipamentoSistema.getNomeSistema());
            stp.setInt(5,equipamentoSistema.getIdSistema());
            
            stp.executeUpdate();
            conn.commit();
            stp.close();
           
        } catch (SQLException ex) {
            try {
                conn.rollback();
            } catch (SQLException e) {
                JOptionPane.showMessageDialog(null,"Falha na execução de rollback. Alteração cancelada. \n" + e.getMessage()) ;
                e.printStackTrace();
            }
            JOptionPane.showMessageDialog(null,"Falha na atualização do registro. \n" + ex.getMessage()) ;
            ex.printStackTrace();
            
        }
    }    

Obrigado !

Um abraço.

Você deve fechar o prepared statement e a conexão num finally, assim você garante que na na ficará preso no banco. EX:


} finally {
if (stp!= null) {
stp.close();
}
if (conn != null) {
conn.close();
}
}

Bom dia colegas !

ronybrand:

Concordo que colocar num finally seria mais adequado, já que garante que seja executado sempre.
Mas considerando que não está ocorrendo nenhuma exception, o que vai mudar colocar no finally ou nessa parte:

        try {
            conn = ConnectionFactory.getInstance().getConnection();
            stp = conn.prepareStatement("Select * from equipamentosistema " +
                                        "order by ec_ecIdSistema");
            rs = stp.executeQuery();  
            while (rs.next()) {
                equipamentoSistemaTemp = new EquipamentoSistema(rs.getInt("ec_ecIdSistema"));
                
                equipamentoSistemaTemp.setEquipamento(
                        new EquipamentoDAO().buscarEquipamento(
                            rs.getInt("ec_eqIdEquipamento")));                
                
                equipamentoSistemaTemp.setCondominio(
                        new CondominioDAO().buscarCondominio(
                            rs.getInt("ec_coIdCondominio")));
                
                equipamentoSistemaTemp.setLocalizacao(rs.getString("ec_ecLocalizacao"));
                equipamentoSistemaTemp.setNomeSistema(rs.getString("ec_ecNomeSistema"));
                
                FacilidadeDAO facilidadeDAO = new FacilidadeDAO();
                equipamentoSistemaTemp.setListaFacilidade(facilidadeDAO.buscarListaFacilidade(equipamentoSistemaTemp));                                
                
                listaequipamentoSistemaTemp.add(equipamentoSistemaTemp);
            }
            rs.close();
            stp.close();
            
        } catch (SQLException ex) {
            JOptionPane.showMessageDialog(null,"Falha na seleção dos registros. \n" + ex.getMessage()) ;
            ex.printStackTrace();
        }

E eu tenho que fechar a conexão para todo comando enviado ao banco ? Porque ?

Obrigado.

Um abraço.

Você pode fechar no final de todos os comandos.
O finally é para garantir que na ocorrência de algum erro na fique nada preso no banco, que se aculumar pode excedecer o número máximo de conexões parando a aplicação além de consumir mais recursos

Boa tarde colegas !

ronybrand:

Então… eu entendi a sua sugestão do finally, mas você acha que isto vai resolver o meu problema inicial ?

Obrigado.

Um abraço.

Boa tarde colegas !

Tentei seguir a dica de fechar a conexão após os inserts e updates, mas agora estou com outro problema.

Eu tenho a classe ConnectionFactory que deve abrir conexões.
Então nas classes que fazem a persistencia de dados eu coloco:

private Connection conn = null;

conn = ConnectionFactory.getInstance().getConnection();        

Só que quando eu fecho a conexão nessas classes parece que esta fechando na ConectionFactory também.

Acho que ficou confuso… mas se alguém entendeu pode me ajudar ?

Obrigado.
Um abraço.

quando for realizar uma nova operação abra novamente uma conexão

Boa tarde colegas !

ronybrand:
Então mas ai é que fica ruim… porque você já viu o tempo que demora para criar uma nova conexão ?
Considerando que eu estou dando o commit, faz sentido ter que fechar a conexão ?

Obrigado.

Um abraço.

usa connection pool, ai a conexão é reaproveitada:

dbcp
http://jakarta.apache.org/commons/dbcp/

ou ainda c3p0

ronybrand:

Se não for abusar você tem um exemplo ?

Obrigado.

Um abraço.

http://www.guj.com.br/posts/list/3033.java#14739

Mas como fazer isso na minha aplicação que é swing ?

Explique mais detalhadamente o quê vc “altera” em uma aplicação que nao “aparece” na outra.
Pode ser que o problema não esteja na conexão.

fabiocsi:

Vamos lá.
Tenho:
-Um banco de dados MySql, onde tenho, por exemplo, uma tabela usuario, este banco esta em um servidor linux.
-Uma aplicação swing que possui uma tela onde posso incluir, excluir, consultar ou alterar registros desta tabela usuario.

Se eu abro a aplicação em duas máquinas e altero por exemplo o nome de um usuario não aparece na outra máquina como alterado. Só se eu fechar a aplicação e abrir de novo.

O que notei é que ao fechar a aplicação e abrir novamente eu obviamente crio uma nova conexão dai ela mostra a alteração feita na outra máquina, mas se eu não faço isso eu mantenho a conexão aberta, então ela não traz os dados atualizados.
Isso vale para inserções e deletes também.

Nos primeiros posts eu coloquei o código da classe que faz cria a conexão e de um método que faz um insert.

Obrigado pela força !

Um abraço.

Isso nos induz a achar que o problema é pelo fato de estar em 2 aplicações, e 1 nao “enxerga” alterações feitas pela outra, no entanto
estamos falando da mesma base de dados.

Faz o seguinte teste:

Esqueça a outra aplicação. Na mesma aplicação que insere o registro, insira uma rotina logo apos que consulta
a tabela onde vc inseriu o registro e vê se ele aparece.

Nao vai ser surpresa se não aparecer… ja tive há uns 2 anos atras um problema assim, eu inseria na tabela
e na mesma tela tinha uma tabela com a lista dos registros nela, e mesmo chamando o metodo de da o refresh
na table a table nao atualizava. Mas eu abria o TOAD e o registro tava la, fisicamente no banco. Nunca mais tive esse problema vou ver se consigo algo que te ajude e te retorno.

Só por desencargo de consciência: troca o executeUpdate() por execute();

fabiocsi:

Realmente MUITO obrigado pela força.

Mas a coisa não é bem assim… na verdade como sempre minha explicação foi confusa, não são duas aplicações que acessam a mesma base, é a mesma aplicação, só que rodando em duas máquinas, como se fossem dois usuarios, entendeu ?

Eu abra a tela de manutenção de usuario em uma máquina pe faço uma alteração, abro a tela de usuario na outra máquina e não enxergo.
A menos que feche e abra a aplicação na segunda máquina.
Na máquina onde eu efetivamente fiz a alteração ela aparece normalmente.
Então exemplificando melhor:

Estou com a aplicação X rodando simultaneamente na maquina A e na maquina B.

Na máquina A, através da tela de cadastro de usuario, altero o nome de um usuário de Joao da Silva para Joao dos Santos.
Na máquina A passo a enxergar Joao dos Santos, posso mudar de registro e voltar, sair da tela de voltar e aparece Joao dos Santos.

Na maquina B, abro a mesma tela de cadastro de usuario e acesso o registro do Joao, e aparece Joao da Silva.
Na máquina B posso mudar de registro e voltar, sair da tela de voltar e continua aparecendo Joao da Silva.

Na maquina B, fecho a aplicação e abro novamente, acesso a tela de usuarios e agora passo a enxergar Joao dos Santos.

No meu caso estou usando o MySql e quando olho a tabela através do MySql Query Browser o registro esta alterado.

Obrigado novamente.

Um abraço.

Meu Deus, acho que estou ficando maluco !

Mas parece que acontece o seguinte:

Se eu faço a alteração na primeira instancia da aplicação ela aparece na segunda.
Agora se eu altero na segunda instancia ela não aparece na primeira.

E olha que eu nem fumo !