Refresh JTable Content

Dear Sirs,

I have a JTable linked to a model.
When the windows holding that JTable is loaded, a resultset, resultSetMetadata, model are generated, and data displayed in the JTable.
Then after, some width are set to columns, let's call it Jtable structure definition.
I noticed that everytime I want to refresh the data after an Insert/update, etc... I am going through the same process which I find not convenient. I use AbstractTableModel.
Is there a  way to refresh data without changing the Jtable structure definition (or redefine it at each refresh)?
I tried
myTableModel.fireTableDataChange() without success.
Omer-PitouAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

zzynxSoftware engineerCommented:
I tried myTableModel.fireTableDataChange() without success.
Nevertheless, using the fireXXXXXX methods on the model is the correct way to go.

I can't say more without seeing some code.
Do you have code to show?
0
Omer-PitouAuthor Commented:
Here we go: (May be a working example using Abstract model to figure out what I am doing wrong)
1. The Intial Table loading
private void loadDataTable() {
        tableComptes.setMySQLString("SELECT * FROM compte ORDER BY numcpte");
        tableModel = new MyResultSetTableModel(tableComptes.getMySQLString());
        tableComptes.setModel(tableModel);
      
    } 

Open in new window

2. The Code to refresh
myToolBarGrid1.getBtnRefresh().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                   tableModel.fireTableDataChanged();
            }
        });

Open in new window

3. The Abstract Model Class (Separate file)
package com.finger.classes;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.table.AbstractTableModel;

public final class MyResultSetTableModel extends AbstractTableModel {
    
    private ResultSetMetaData rsmd;
    private ResultSet rs;
    private MyDBAccessManager myDBAccessMgr;
    
    public MyResultSetTableModel (String pSQLStmt) {
        setQuery(pSQLStmt);       
    }   
    
    public void setQuery(String pSQLStmt) {
        try {
            if (myDBAccessMgr == null) {
                myDBAccessMgr = new MyDBAccessManager();
            }
             
            rs = myDBAccessMgr.executeQuery(pSQLStmt);       
            rsmd = rs.getMetaData();
            this.fireTableStructureChanged();
        } catch (SQLException ex) {
            Logger.getLogger(MyResultSetTableModel.class.getName()).log(Level.SEVERE, null, ex);
        }        
    }
 
    @Override
    public Class getColumnClass(int column) {
        try {
            String className = rsmd.getColumnClassName(column + 1);
            return Class.forName(className);
        } catch (SQLException | ClassNotFoundException exception) {
            JOptionPane.showMessageDialog(null, exception.getMessage());
        }
        return Object.class;
    }             
    @Override
    public int getColumnCount() {
        try {
            return rsmd.getColumnCount();
        } catch (SQLException sqlException) {
            JOptionPane.showMessageDialog(null, sqlException.getMessage());
        }
        return 0;
    } 
    @Override
    public String getColumnName(int column) {
        try {
            return rsmd.getColumnName(column + 1);
        } catch (SQLException sqlException) {
            JOptionPane.showMessageDialog(null, sqlException.getMessage());
        }
        return "";
    }   
    @Override
    public int getRowCount() {
        try {
            rs.last();
            return rs.getRow();
        } catch (SQLException ex) {
            Logger.getLogger(MyResultSetTableModel.class.getName()).log(Level.SEVERE, null, ex);
        }
        return 0;            
    }
    @Override
    public Object getValueAt(int row, int column) {
        try {
            rs.absolute(row + 1);
            return rs.getObject(column + 1);
        } catch (SQLException sqlException) {
            JOptionPane.showMessageDialog(null, sqlException.getMessage());
        }
        return null; // ""
    }            
}

Open in new window

package com.finger.classes;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.table.AbstractTableModel;

public final class MyResultSetTableModel extends AbstractTableModel {
    
    private ResultSetMetaData rsmd;
    private ResultSet rs;
    private MyDBAccessManager myDBAccessMgr;
    
    public MyResultSetTableModel (String pSQLStmt) {
        setQuery(pSQLStmt);       
    }   
    
    public void setQuery(String pSQLStmt) {
        try {
            if (myDBAccessMgr == null) {
                myDBAccessMgr = new MyDBAccessManager();
            }
             
            rs = myDBAccessMgr.executeQuery(pSQLStmt);       
            rsmd = rs.getMetaData();
            this.fireTableStructureChanged();
        } catch (SQLException ex) {
            Logger.getLogger(MyResultSetTableModel.class.getName()).log(Level.SEVERE, null, ex);
        }        
    }
 
    @Override
    public Class getColumnClass(int column) {
        try {
            String className = rsmd.getColumnClassName(column + 1);
            return Class.forName(className);
        } catch (SQLException | ClassNotFoundException exception) {
            JOptionPane.showMessageDialog(null, exception.getMessage());
        }
        return Object.class;
    }             
    @Override
    public int getColumnCount() {
        try {
            return rsmd.getColumnCount();
        } catch (SQLException sqlException) {
            JOptionPane.showMessageDialog(null, sqlException.getMessage());
        }
        return 0;
    } 
    @Override
    public String getColumnName(int column) {
        try {
            return rsmd.getColumnName(column + 1);
        } catch (SQLException sqlException) {
            JOptionPane.showMessageDialog(null, sqlException.getMessage());
        }
        return "";
    }   
    @Override
    public int getRowCount() {
        try {
            rs.last();
            return rs.getRow();
        } catch (SQLException ex) {
            Logger.getLogger(MyResultSetTableModel.class.getName()).log(Level.SEVERE, null, ex);
        }
        return 0;            
    }
    @Override
    public Object getValueAt(int row, int column) {
        try {
            rs.absolute(row + 1);
            return rs.getObject(column + 1);
        } catch (SQLException sqlException) {
            JOptionPane.showMessageDialog(null, sqlException.getMessage());
        }
        return null; // ""
    }            
}

Open in new window

0
zzynxSoftware engineerCommented:
First of all some remarks:

1) this is strange code:
private void loadDataTable() {
        tableComptes.setMySQLString("SELECT * FROM compte ORDER BY numcpte");
        tableModel = new MyResultSetTableModel(tableComptes.getMySQLString());
        tableComptes.setModel(tableModel);
}

Open in new window


In the first line you set a select string on your table. Does your table really need that query string? (I think your model does, but not your table itself.)
(Can I see the class code 'tableComptes' is an instance of?)
In the second line you create your model using that string which you ask again from your table. ???

I would expect a method initTable that you call ONCE at setup:

private void initDataTable() {
        tableModel = new MyResultSetTableModel("SELECT * FROM compte ORDER BY numcpte");
        tableComptes.setModel(tableModel);
}

Open in new window


and then to refresh:

private void loadData(String newQuery) {
        tableModel.setQuery(newQuery);
}

Open in new window


and since inside your setQuery() method you call
this.fireTableStructureChanged();

Open in new window

that automatically updatesyour JTable.

2) Having this code:
myToolBarGrid1.getBtnRefresh().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                   tableModel.fireTableDataChanged();
            }
        });

Open in new window

Just pressing the refresh button won't do anything.
Yes, you fire a tableDataChanged event, but your model isn't changed, so you won't see any difference in your table.

I would expect something like this:
myToolBarGrid1.getBtnRefresh().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                   tableModel.setQuery("SELECT * FROM compte ORDER BY numcpte");
            }
        });

Open in new window


Will the query always be the same "SELECT * FROM compte ORDER BY numcpte"?
If it is, I would store it in the table model:

  private String query;

  public void setQuery(String pSQLStmt) {
        this.query = pSQLStmt; 
  }

  public void refreshData() {
        try {
            if (myDBAccessMgr == null) {
                myDBAccessMgr = new MyDBAccessManager();
            }
            rs = myDBAccessMgr.executeQuery(this.query);       
            rsmd = rs.getMetaData();
            this.fireTableStructureChanged();
        } catch (SQLException ex) {
            Logger.getLogger(MyResultSetTableModel.class.getName()).log(Level.SEVERE, null, ex);
        }        
    }

Open in new window


Then in your code of the button you could write:

myToolBarGrid1.getBtnRefresh().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                   tableModel.refreshData();
            }
});

Open in new window


Last thing:
Does your structure really change?
If not inside the refreshData() method, you'd better use
fireTableDataChanged()

Open in new window

instead of
fireTableStructureChanged()

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

Omer-PitouAuthor Commented:
Thanks zznyx for your prompt reply.
- I want to mention that I am using a custom class extending JTable. On top of attributes, methods, etc... I can inherit, I have my own attributes and methods built in that custom class. i,e, mySQLString is an  attribute holding the default SQL statement, and can change depending on filter made by user (I am using pure SQL Statements to filter in order to benefit from indexes set on the table). Some of my own methods are like export2CSV(), export2XLS(), export2TXT(), etc... so I don't have to re-type all the codes every time I want to do these operations and this makes maintenance ease.  I AGREE WITH YOU that it shouldn't be put in the custom JTable, I will move it to the model custom class.
- AFTER READING YOUR INPUTS, i figured out what I was doing wrong and was making my structure to be changed everytime  I call setQuery method of my model. I changed fireTableStructureChanged() to  fireTableDataChanged(), and it works as expected. THANK YOU AGAIN.

Honnestly, the last 4 weeks weren't easy for me. Translating a dBASE application in Java. This has been challenging, I really like it. Still need to deal with jasperReports, and hope packing and deploying the application won't be a big deal.

AGAIN THANK YOU FOR YOUR TIME, I really appreciate your inputs and happy to be a part of this forum.

Regards.
0
zzynxSoftware engineerCommented:
Thanks for your kind words. (That's rather rare these days)
Glad I could help you.
Good luck
0
Omer-PitouAuthor Commented:
You re welcome
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.