JTable não atualiza dados quando inserido via banco ou por outro usuário

Bom dia!

Eu estou desenvolvendo um sistema em Java que utiliza MySQL e Hibernate (cliente servidor) e quando insiro dados via banco, os mesmos não aparecem na minha JTable. Nem adianta fechar a tela e abrir novamente. Somente quando fecho todo o sistema. E isso é um grande problema para mim pois se um usuário insere um registro o outro não consegue saber. O mesmo só consegue ver o registro inserido por um outro quando insere o próprio dele. Aí, o registro que “está faltando” é listado.

Alguém poderia me ajudar?

Caso não tenham entendido o problema, aqui vai um exemplo do que acontece:

[b]Usuário 1 insere o cliente João
Sistema atualiza a JTable do usuário 1 e o mesmo aparece.

Usuário 2 insere o cliente Marcos
Se o usuário tentar listar os clientes, o cliente Marcos inserido pelo Usuário 2 não aparece.

Usuário 1 insere o cliente Alan
Sistema atualiza a JTable e lista João, Marcos e Alan[/b]

Aqui segue o código do meu modelo de tabela:


package modelo;

import anotacao.CampoTabela;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import util.Persistencia;
import util.Utilitario;

/**
 *
 * @author Alan
 */
public class ModeloTabelaGenerico extends AbstractTableModel {

    private Class entidade;
    private List lista;
    private List<Field> colunas;    

    public ModeloTabelaGenerico(Class e) {
        colunas = new ArrayList<Field>();
        entidade = e;
        adicionaCampos(entidade);        
        consulta();
    }

    private void adicionaCampos(Class classe) {
        Class superClasse = classe.getSuperclass();
        if (!superClasse.equals(Object.class)) {
            adicionaCampos(superClasse);
        }
        for (Field f : classe.getDeclaredFields()) {
            if (f.isAnnotationPresent(CampoTabela.class)) {
                colunas.add(f);
            }
        }

    }

    private void consulta() {
        Session session = Persistencia.getInstancia().getSessionFactory().openSession();
        Query q = session.createQuery("from " + entidade.getSimpleName() + " obj" );
        lista = q.list();
        session.close();
    }

    @Override
    public int getRowCount() {
        return lista.size();
    }

    @Override
    public int getColumnCount() {
        return colunas.size();
    }

    @Override
    public String getColumnName(int columnIndex) {
        CampoTabela ct = colunas.get(columnIndex).getAnnotation(CampoTabela.class);
        return ct.etiqueta();
    }

    @Override
    public Class getColumnClass(int columnIndex) {
        if(colunas.get(columnIndex).getType().equals(Double.class)){
            return String.class;
        }else{
            return colunas.get(columnIndex).getType();
        }
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        try {
            Field atributo = colunas.get(columnIndex);
            atributo.setAccessible(true);
            Object objeto = lista.get(rowIndex);
            if(atributo.get(objeto)!=null){
                if(atributo.get(objeto).getClass().equals(Double.class)){
                    return Utilitario.formataMoeda((Double)atributo.get(objeto));
                }else{
                    return atributo.get(objeto);
                }
            }
            
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        Session session = null;
        try {
            session = Persistencia.getInstancia().getSessionFactory().openSession();
            Transaction transaction = session.beginTransaction();
            Field atributo = colunas.get(columnIndex);
            atributo.setAccessible(true);
            Object objeto = lista.get(rowIndex);
            atributo.set(objeto, aValue);
            session.merge(objeto);
            transaction.commit();
            consulta();
            fireTableDataChanged();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            session.close();
        }
    }

    public List getLista() {
        return lista;
    }

}

E aqui da minha tela que utiliza a JTable:


package visao;

import anotacao.CampoTabela;
import controlador.Controlador;
import excecao.RegistroNaoAlteradoException;
import excecao.RegistroNaoInseridoException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.PatternSyntaxException;
import javax.persistence.NoResultException;
import javax.swing.*;
import javax.swing.event.ChangeListener;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import modelo.ModeloTabelaGenerico;
import util.Utilitario;


/**
 *
 * @author Alan
 */
public abstract class SuperTela extends javax.swing.JInternalFrame implements ActionListener, ChangeListener {
    private JPanel painelBotoesCadastro;
    private JPanel painelSuperiorPesquisa;
    private JPanel painelInferiorPesquisa;
    private JTextField txtCampoPesquisa;
    private JButton btnPesquisar;
    private JButton btnNovo;
    private JButton btnGravar;
    private JButton btnExcluir;
    private JButton btnCancelar;
    private JButton btnFechar;
    private JTableHeader header;
    private Integer coluna;
    protected JTable tblRegistros;
    protected JTabbedPane abasPrincipal;
    private JPanel telaPesquisa;
    protected JPanel telaCadastro;
    protected Object objeto;
    private TableRowSorter<TableModel> sorter = null;
    protected Class classe;
    private Component componenteAFocalizar;

    protected abstract void setEntidade(Object entidade);

    protected abstract Object getEntidade();

    protected abstract Class getClasse();

    protected abstract Component aFocalizar();

    public SuperTela() {
        setResizable(true);
        setMaximizable(true);
        setIconifiable(true);
        setClosable(true);
        setBorder(BorderFactory.createLineBorder(Color.BLACK));
        setSize(WIDTH, HEIGHT);
        
        //centralizaJanela();
        abasPrincipal = new JTabbedPane();
        telaPesquisa = new JPanel(new BorderLayout());
        telaCadastro = new JPanel(new BorderLayout());
        txtCampoPesquisa = new JTextField(50);
        btnPesquisar = new JButton("Pesquisar");
        btnPesquisar.addActionListener(this);
        btnPesquisar.setMnemonic('P');
        btnNovo = new JButton("Novo");
        btnNovo.addActionListener(this);
        btnNovo.setMnemonic('N');
        painelSuperiorPesquisa = new JPanel();
        painelInferiorPesquisa = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        btnGravar = new JButton("Gravar");
        btnGravar.addActionListener(this);
        btnGravar.setMnemonic('G');
        btnExcluir = new JButton("Excluir");
        btnExcluir.addActionListener(this);
        btnExcluir.setMnemonic('E');
        btnCancelar = new JButton("Cancelar");
        btnCancelar.addActionListener(this);
        btnCancelar.setMnemonic('C');
        btnFechar = new JButton("Fechar");
        btnFechar.addActionListener(this);
        btnFechar.setMnemonic('F');

        painelBotoesCadastro = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        tblRegistros = new JTable();
        classe = getClasse();
        criarTabela();
        JScrollPane j = new JScrollPane(tblRegistros);
        telaPesquisa.add(j, BorderLayout.CENTER);

        tblRegistros.addMouseListener(new java.awt.event.MouseAdapter() {

            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                tblRegistrosMouseClicked(evt);
            }
        });

        header = tblRegistros.getTableHeader();
        header.addMouseListener(new java.awt.event.MouseAdapter() {

            @Override
            public void mouseClicked(java.awt.event.MouseEvent e) {
                coluna = header.columnAtPoint(e.getPoint());
            }
        });

        txtCampoPesquisa.addKeyListener(new java.awt.event.KeyAdapter() {

            @Override
            public void keyPressed(java.awt.event.KeyEvent evt) {
                txtCampoPesquisaKeyPressed(evt);
            }
        });


        painelBotoesCadastro.setBorder(BorderFactory.createEtchedBorder());

        painelBotoesCadastro.add(btnGravar);
        painelBotoesCadastro.add(btnExcluir);
        painelBotoesCadastro.add(btnCancelar);
        telaCadastro.add(painelBotoesCadastro, BorderLayout.SOUTH);

        painelSuperiorPesquisa.setBorder(BorderFactory.createEtchedBorder());
        painelSuperiorPesquisa.add(txtCampoPesquisa);
        painelSuperiorPesquisa.add(btnPesquisar);
        painelSuperiorPesquisa.add(btnNovo);

        telaPesquisa.add(painelSuperiorPesquisa, BorderLayout.NORTH);

        painelInferiorPesquisa.setBorder(BorderFactory.createEtchedBorder());
        painelInferiorPesquisa.add(btnFechar, new FlowLayout(FlowLayout.RIGHT));
        telaPesquisa.add(painelInferiorPesquisa, BorderLayout.SOUTH);

        abasPrincipal.addTab("Pesquisa", telaPesquisa);
        abasPrincipal.addTab("Cadastro", telaCadastro);
        abasPrincipal.addChangeListener(this);

        add(abasPrincipal);

        pack();
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    }

    private void criarTabela() {
        tblRegistros.setModel(new ModeloTabelaGenerico(classe));
        sorter = new TableRowSorter<TableModel>(tblRegistros.getModel());
        tblRegistros.setRowSorter(sorter);
        tblRegistros.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
        List<Integer> tamanhoDosCampos = descobreTamanhoDosCampos(classe);
        
        for (int i=0; i < tamanhoDosCampos.size(); i++) {
            tblRegistros.getColumnModel().getColumn(i).setPreferredWidth(tamanhoDosCampos.get(i));
        }
    }

    private void alterarRegistros() {
        abasPrincipal.setEnabled(false);
        btnExcluir.setEnabled(true);
        int linhaSelecionada = tblRegistros.getSelectedRow();
        int linhaModelo = tblRegistros.convertRowIndexToModel(linhaSelecionada);
        ModeloTabelaGenerico mtg = (ModeloTabelaGenerico) tblRegistros.getModel();
        objeto = mtg.getLista().get(linhaModelo);
        setEntidade(objeto);
    }

    @Override
    public void stateChanged(javax.swing.event.ChangeEvent evt) {
        if (btnNovo.isFocusOwner()) {
            novo();
        } else if (evt.getSource() == abasPrincipal) {
            if (telaCadastro.requestFocusInWindow()) {
                if (tblRegistros.getSelectedRow() == -1) {
                    novo();
                } else {
                    alterarRegistros();
                }
            }
        }
    }

    private void tblRegistrosMouseClicked(MouseEvent evt) {
        if (evt.getClickCount() > 1) {
            abasPrincipal.setSelectedIndex(1);
        }
    }

    private void novo() {
        abasPrincipal.setEnabled(false);
        btnExcluir.setEnabled(false);
        abasPrincipal.setSelectedIndex(1);
        //btnLog.setEnabled(false);
        componenteAFocalizar = aFocalizar();
        componenteAFocalizar.requestFocusInWindow();
    }

    public Object getDadosTabela() {
        ModeloTabelaGenerico mtg = (ModeloTabelaGenerico) tblRegistros.getModel();
        return mtg.getLista();
    }

    private void pesquisar() {
        if (txtCampoPesquisa.getText().length() == 0) {
            sorter.setRowFilter(null);
        } else {
            try {
                if (coluna == null) {
                    sorter.setRowFilter(
                            RowFilter.regexFilter("(?i)" + txtCampoPesquisa.getText()));
                } else {
                    sorter.setRowFilter(
                            RowFilter.regexFilter("(?i)" + txtCampoPesquisa.getText(), coluna));
                }
            } catch (PatternSyntaxException pse) {
                JOptionPane.showMessageDialog(this, "Erro no Filtro!",
                        "Erro!", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    private void txtCampoPesquisaKeyPressed(KeyEvent evt) {
        if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
            pesquisar();
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        if (e.getSource() == btnGravar) {

            Long codigo = null;
            Controlador controlador = new Controlador();
            objeto = getEntidade();

            if (objeto != null) {
                Method[] arrayDeMetodos = objeto.getClass().getMethods();
                for (Method metodo : arrayDeMetodos) {
                    if (metodo.getName().equals("getId")) {
                        try {
                            codigo = (Long) metodo.invoke(objeto);
                        } catch (IllegalAccessException ex) {
                            Logger.getLogger(SuperTela.class.getName()).log(Level.SEVERE, null, ex);
                        } catch (IllegalArgumentException ex) {
                            Logger.getLogger(SuperTela.class.getName()).log(Level.SEVERE, null, ex);
                        } catch (InvocationTargetException ex) {
                            Logger.getLogger(SuperTela.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }

                }

                if (codigo == null) {
                    try {
                        abasPrincipal.setEnabled(true);
                        controlador.inserir(objeto);
                        JOptionPane.showMessageDialog(this, "Registro inserido com sucesso!",
                                "Aviso!", JOptionPane.WARNING_MESSAGE);
                    } catch (RegistroNaoInseridoException ex) {
                        JOptionPane.showMessageDialog(this, "Registro não inserido!",
                                "Erro!", JOptionPane.ERROR_MESSAGE);
                    }

                } else {

                    try {
                        controlador.alterar(objeto);
                        JOptionPane.showMessageDialog(this, "Registro alterado com sucesso!",
                                "Aviso!", JOptionPane.WARNING_MESSAGE);
                    } catch (RegistroNaoAlteradoException ex) {
                        JOptionPane.showMessageDialog(this, "Registro não alterado!",
                                "Erro!", JOptionPane.ERROR_MESSAGE);
                    }
                }

                Utilitario.limpaCadastro(telaCadastro);
                abasPrincipal.setSelectedIndex(0);
                abasPrincipal.setEnabled(true);
                criarTabela();
            }



        } else if (e.getSource() == btnExcluir) {

            if (JOptionPane.showConfirmDialog(this, "Tem certeza que deseja remover este registro?",
                    "Confirmar", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
                int linhaSelecionada = tblRegistros.getSelectedRow();
                int linhaModelo = tblRegistros.convertRowIndexToModel(linhaSelecionada);
                ModeloTabelaGenerico mtg = (ModeloTabelaGenerico) tblRegistros.getModel();
                objeto = mtg.getLista().get(linhaModelo);
                Controlador controlador = new Controlador();
                try {
                    controlador.excluir(objeto);
                    JOptionPane.showMessageDialog(this, "Registro excluído com sucesso!",
                            "Aviso!", JOptionPane.WARNING_MESSAGE);
                    Utilitario.limpaCadastro(telaCadastro);
                    abasPrincipal.setEnabled(true);
                    criarTabela();
                    abasPrincipal.setSelectedIndex(0);
                } catch (NoResultException ex) {
                    JOptionPane.showMessageDialog(this, "Este registro já foi excluído!",
                            "Erro!", JOptionPane.ERROR_MESSAGE);
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(this, "Não é possível excluir este registro!\nExiste um ou mais registros vinculados a ele!",
                            "Erro!", JOptionPane.ERROR_MESSAGE);
                }
            }
        } else if (e.getSource() == btnCancelar) {
            abasPrincipal.setEnabled(true);
            Utilitario.limpaCadastro(telaCadastro);
            criarTabela();
            abasPrincipal.setSelectedIndex(0);
        } else if (e.getSource() == btnNovo) {
            novo();
        } else if (e.getSource() == btnPesquisar) {
            pesquisar();
        } else if (e.getSource() == btnFechar) {
            MenuPrincipal.fX += -10;
            MenuPrincipal.fY += -10;
            SuperTela.this.dispose();
        }
    }
    
    private ArrayList<Integer> descobreTamanhoDosCampos(Class classe) {
        ArrayList<Integer> tamanhoDosCampos = new ArrayList<Integer>();
        
        Class superClasse = classe.getSuperclass();
        if (!superClasse.equals(Object.class)) {
            descobreTamanhoDosCampos(superClasse);
        }
        for (Field f : classe.getDeclaredFields()) {
            if (f.isAnnotationPresent(CampoTabela.class)) {
                CampoTabela campoTabela = f.getAnnotation(CampoTabela.class);
                tamanhoDosCampos.add(campoTabela.tamanhoExibicao());
            }
        }
        
        return tamanhoDosCampos;
    }
}

Desde já agradeço

Cara tenta colocar um botão “Refresh”, na qual faz a mesma listagem no inicio do programa.

Cria uma rotina que faça ele atualizar sozinha!

O que eu não entendi é porque não atualiza.
Eu comecei a chamar o método criaTabela() ao abrir a tela e ao pesquisar.
Imaginava que isso iria atualizá-la mas não. :?

Pesquisa sobre Thread … com isso acredito que você vai conseguir resolver seu problema!!!