JTable getValueAt method cast to Integer exception - java

I use this code to get my ID number of my JTable,
But "AWT-EventQueue-0" java.lang.ClassCastException occur,
public void actionPerformed(ActionEvent e) {
if (e.getSource() == dellButton) {
try {
int rowToDelete = 0;
int rowToModel = 0;
if (table.getSelectedRow() > -1) {
rowToDelete = table.getSelectedRow();
rowToModel = table.convertRowIndexToModel(rowToDelete);
tableModel.removeRow(rowToModel);
}
} catch (SQLException sqle) {
sqle.printStackTrace();
}
}
}
My TableModel.removeRow() method:
...
public void removeRow(int rowNumber) throws SQLException {
String removeQuery = "delete from mytable where id=?";
PreparedStatement pStatement = con.prepareStatement(removeQuery);
pStatement.setInt(1, rowNumber);
int rowsAffected = pStatement.executeUpdate();
}
...

int rowID = (int) table.getValueAt(selectedRowIndex, 0); is useless code line,
code line tableModel.removeRow(rowID, rowIndex); has wrong paramaters
test if any row is selected, otherwise selected row returns -1
everything could be only
#Override
public void actionPerformed(ActionEvent e) {
int rowToDelete = 0;
int rowToModel = 0;
if (table.getSelectedRow() > -1) {
rowToDelete = table.getSelectedRow();
rowToModel = table.convertRowIndexToModel(rowToDelete);
model.removeRow(rowToModel);
}
}
be sure that your SelectionMode will be, otherwise you would need to loop inside arrays of selected rows,
table.getSelectionModel().setSelectionMode(
ListSelectionModel.SINGLE_SELECTION);

Related

How to remove row from table after deleting the the product?

Hello when I delete a product from database through a table using a popupMenu (Right click Button) the row still shows up in the table list, the insertProduct method is working fine and inserts the row to table but the removeProduct method doesn't work can you tell me where is the problem in my code please ?
ProductTable.java:
public class ProductTable extends AbstractTableModel {
ProductsDao pd = new ProductsDao();
private final List<Products> products;
public ProductTable() throws Exception {
this.patients = (ArrayList<Products>) pd.getProductsList();
}
private String[] columnNames = {"PRODUCT NAME", "PRODUCT CATEGORY", "PRODUCT PRICE"};
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public String getColumnName(int column) {
return columnNames[column];
}
#Override
public int getRowCount() {
return products.size();
}
#Override
public Object getValueAt(int row, int column) {
Products p = products.get(row);
switch (column)
{
case 0: return p.getProductName();
case 1: return p.getProductCategory();
case 2: return p.getProductPrice();
}
}
#Override
public void setValueAt(Object value, int row, int column) {
Products p = products.get(row);
switch (column) {
case 0: p.setProductName((String)value); break;
case 1: p.setProductCategory((Date)value); break;
case 2: p.setProductPrice((int)value); break;
}
fireTableCellUpdated(row, column);
}
public Products getProduct(int row) {
return products.get(row);
}
public void addProduct(Products p) {
insertProduct(getRowCount(), p);
}
public void insertProduct(int row, Products p) {
products.add(row, p);
fireTableRowsInserted(row, row);
}
public void deleteProduct(Products p) {
removeProduct(getRowCount(), p);
}
public void removeProduct(int row, Products p) {
products.remove(row);
fireTableRowsDeleted(row, row);
}
}
JFrame :
public void popupTable() {
JPopupMenu popupMenu = new JPopupMenu();
JMenuItem menuItem1 = new JMenuItem("Delete", new ImageIcon(getClass().getResource("")));
menuItem1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int row = jTable1.getSelectedRow();
String cell = jTable1.getModel().getValueAt(row, 0).toString();
Products p = new Products();
p.setId(cell);
try {
int count = ProductsDao.getInstance().delete(p);
if (count == 1) {
removeRowFromTable(p);
JOptionPane.showMessageDialog(null, "Deleted");
} else {
JOptionPane.showMessageDialog(null, "Faild");
}
} catch (Exception ex) {
Logger.getLogger(AddNewPatient.class.getName()).log(Level.SEVERE, null, ex);
}
});
popupMenu.add(menuItem1);
jTable1.setComponentPopupMenu(popupMenu);
}
public static void removeRowFromTable(Products data) {
ProductTable t = (ProductTable) jTable1.getModel();
t.deleteProduct(data);
}
ProductsDao.java:
#Override
public List<Products> getProductsList() throws Exception {
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
ArrayList<Products> products = new ArrayList<Products>();
try {
con = getConnection();
String sql = "SELECT * FROM products ORDER BY PRODUCT_ID DESC";
ps = con.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next()) {
Products product = new Products();
product.setProductName(rs.getString("PRODUCT_NAME"));
product.setProductCategory(rs.getString("PRODUCT_CATEGORY"));
product.setProductPrice(rs.getInt("PRODUCT_PRICE"));
products.add(product);
}
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex.getMessage());
} finally {
rs.close();
ps.close();
closeConnection(con);
}
return products;
}
These methods don't make sense I'm afraid:
public void deleteProduct(Products p) {
removeProduct(getRowCount(), p);
}
public void removeProduct(int row, Products p) {
products.remove(row);
fireTableRowsDeleted(row, row);
}
since you never really use the Products parameter, p, in any useful way to identify where it is in the table model. Also, I'm not really sure why you have two methods, and what they are each supposed to represent.
Instead, assuming that products in your TableModel is an ArrayList<Products>, and assuming that you've overridden Products equals and hashCode methods appropriately, you need to find the index of the selected item in the list and then remove it from the list and notify the listeners that this has been performed. Something like:
public void deleteProduct(Products p) {
int row = products.indexOf(p);
products.remove(row);
fireTableRowsDeleted(row, row);
}
This will only work if you override equals and hashCode correctly for Products.

Updating dynamically JTable(s)

I'm working on a Java database application, where the user has one side to insert data and another to show in a JTable (in a JScrollPane) the content of the linked HSQLDB database. Everthing works so far so good, but I searched for a very long time without finding how to update my JTable dynamically when a change is made to the database (add, update or delete) for each instance of my program because several persons can work on it simultaneously.
It actually works by replacing my table model for local update, but for other instances, i have set a Timer which is not very clean.
Could you help me resolving this please ?
Here is my code (I have an Interface.java for "visible" part and a SQL.java to manage my db) :
My timer
JTable table = new JTable(sql.showTable("SELECT * FROM suivi_flotte"));
Timer timer = new Timer(900000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
sql.updateTable();
nbLinesOrRefresh.setText("Actualisation...");
Timer timer2 = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
nbLinesOrRefresh.setText("");
}
});
timer2.start();
timer2.setRepeats(false);
}
});
timer.setDelay(900000);
timer.start();
formatTable(table);
My updateTable() method (called each time there is an insert, update or delete)
protected void updateTable() {
Interface.f.table.setModel(showTable("SELECT * FROM suivi_flotte"));
Interface.f.formatTable(Interface.f.table); // a method to custom JTable appearance
}
My showTable(String query) method
protected DefaultTableModel showTable(String query) {
String[] columnsTitles = {"N°", "Propriétaire", "Service", "Grade", "Nom", "Prénom", "Mail", "N° SIM", "N° Tél", "Modèle", "N° Série", "IMEI", "N° Crypto", "Date début", "Date fin", "DS", "Commentaire", "Date de création"};
ArrayList<String> columnNames = new ArrayList<>();
ArrayList<Object> data = new ArrayList<>();
connectDB(); // only to connect to db
try (ResultSet rs = stmt.executeQuery(query)) {
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
for (int i = 1; i <= columns; i++) {
columnNames.add(columnsTitles[i - 1]);
}
while (rs.next()) {
ArrayList<Object> row = new ArrayList<>(columns);
for (int i = 1; i <= columns; i++) {
row.add(rs.getObject(i));
}
data.add(row);
}
shutdownDB(); // to fully disconnect from db
} catch (SQLException e) {
System.out.println(e.getMessage());
}
Vector<Vector<?>> dataVector = new Vector<>();
Vector<String> columnNamesVector = new Vector<>();
for (int i = 0; i < data.size(); i++) {
ArrayList<?> subArray = (ArrayList<?>) data.get(i);
Vector<Object> subVector = new Vector<>();
for (int j = 0; j < subArray.size(); j++) {
subVector.add(subArray.get(j));
}
dataVector.add(subVector);
}
for (int i = 0; i < columnNames.size(); i++) {
columnNamesVector.add(columnNames.get(i));
}
DefaultTableModel tModel = new DefaultTableModel(dataVector, columnNamesVector) {
private static final long serialVersionUID = 1L;
public Class<?> getColumnClass(int column) {
for (int row = 0; row < getRowCount(); row++) {
Object o = getValueAt(row, column);
if (o != null) {
return o.getClass();
}
}
return Object.class;
}
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
// tModel.fireTableDataChanged(); // <-- does not work
return tModel;
}
Thank you for your help.
UPDATE 1 :
All my connection/disconnection code :
private void connectDB() {
JFrame op = new JFrame();
op.setAlwaysOnTop(true);
try {
Class.forName("org.hsqldb.jdbcDriver");
co = DriverManager.getConnection("jdbc:hsqldb:file:db;shutdown=true");
stmt = co.createStatement();
} catch (SQLException | ClassNotFoundException e) {
JOptionPane.showMessageDialog(op, "Erreur de connexion à la base de données :\n" + e.getMessage(), Interface.windowTitle, JOptionPane.ERROR_MESSAGE);
}
}
private void openDB() throws IOException {
try {
BufferedReader br = new BufferedReader(new FileReader("db.sql"));
String line;
StringBuffer sb = new StringBuffer();
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
stmt.executeUpdate(sb.toString());
} catch (SQLException e) {}
}
private void shutdownDB() throws SQLException {
stmt.close();
co.close();
}
UPDATE 2 :
I changed everything in SQL.java to non-static. Each SQL.[...] has been changed to sql.[...] with private SQL sql = new SQL(); on top of the class and public SQL() {} in the class. I also changed it in the above code.

Invalid range error in Jtable when i use TableRowSorter

When I use TableRowSorter on my table I get an invalid range error, but when I delete jTableWells.setRowSorter(rowSorter), all it works successfully.
this.rowSorter = new TableRowSorter(jTableWells.getModel());
jTableWells.setRowSorter(rowSorter);
searchTextField.getDocument().addDocumentListener(new DocumentListener(){
#Override
public void insertUpdate(DocumentEvent e) {
String text = searchTextField.getText();
if (text.trim().length() == 0) {
rowSorter.setRowFilter(null);
} else {
rowSorter.setRowFilter(RowFilter.regexFilter("(?i)" + text));
}
}
#Override
public void removeUpdate(DocumentEvent e) {
String text = searchTextField.getText();
if (text.trim().length() == 0) {
rowSorter.setRowFilter(null);
} else {
rowSorter.setRowFilter(RowFilter.regexFilter("(?i)" + text));
}
}
});
When I try to update the table with displayTableWells() after adding a new row, I got the error of Invalid range:
private int addNewRecord() {
try{
...
st.executeUpdate(sql,Statement.RETURN_GENERATED_KEYS);
rs = st.getGeneratedKeys();
if ( rs.next() ) {
...
JOptionPane.showMessageDialog(this, "Saved ");
}
displayTableWells();// for update the table
}
}
...
}
private void displayTableWells() {
int i;
int count;
String a[];
String header[] = {"col1","col2","col3"};
count = header.length;
DefaultTableModel tm = new DefaultTableModel();
//First set the Table header
for(i = 0; i < count; i++)
{
tm.addColumn(header[i]);
}
a = new String[count];
try
{
st = conn.createStatement();
rs = st.executeQuery("SELECT col1,col2,col3 from table ORDER
BY createdon DESC");
while (rs.next())
{
for(i = 0; i < count; i++)
{
a[i] = rs.getString(i+1);
}
tm.addRow(a); //Adding the row in table model
jTableWells.setModel(tm);
}
}
catch (SQLException se) {
...
}
}
The error as bellow :
Exception in thread "AWT-EventQueue-0"
java.lang.IndexOutOfBoundsException: Invalid range
at javax.swing.DefaultRowSorter.rowsInserted(DefaultRowSorter.java:864)
at javax.swing.JTable.notifySorter(JTable.java:4270) at
javax.swing.JTable.sortedTableChanged(JTable.java:4118) at
javax.swing.JTable.tableChanged(JTable.java:4395) at
javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableModel.java:296)
at
javax.swing.table.AbstractTableModel.fireTableRowsInserted(AbstractTableModel.java:231)
at
javax.swing.table.DefaultTableModel.insertRow(DefaultTableModel.java:376)
at
javax.swing.table.DefaultTableModel.addRow(DefaultTableModel.java:350)
at
javax.swing.table.DefaultTableModel.addRow(DefaultTableModel.java:361)
at
org.geotools.geophysicsdbmaven.NewWell.displayTableWells(NewWell.java:474)

jtable refresh in setModel

I'm following this example code to create my own tableModel class to display data from a db using cachedRowSet, and use rowSetEvent to refresh the table when insert a row and delete a row to the cachedRowSet.
https://github.com/abissell/jdbctutorial/blob/master/src/com/oracle/tutorial/jdbc/CoffeesTableModel.java
public void rowChanged(RowSetEvent event) {
try {
tm.rs.moveToCurrentRow();
tm = new MyTableModel(tm.rs); // to get right row nums
table.setModel(tm);
} catch (SQLException er) {
er.printStackTrace();
}
}
public class MyTableModel extends AbstractTableModel {
CachedRowSet rs;
ResultSetMetaData meta;
int cols, rows;
public MyTableModel(CachedRowSet r) {
rs = r;
try {
meta = rs.getMetaData();
cols = meta.getColumnCount();
rs.beforeFirst();
rows = 0;
while (rs.next()) {
rows++;
}
rs.beforeFirst();
} catch(SQLException e) {
e.printStackTrace();
}
}
public void insert(String[] info) {
try {
rs.moveToInsertRow();
for(int i = 0;i < cols;i++) {
rs.updateString(i+1, info[i]);
}
rs.insertRow();
rs.moveToCurrentRow();
} catch(SQLException e) {
e.printStackTrace();
}
}
public void delete(int id) {
try {
rs.beforeFirst();
while(rs.next()) {
if(Integer.parseInt(rs.getString(1))==id) {
rs.deleteRow();
break;
}
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
#Override
public int getRowCount() {
return rows;
}
#Override
public int getColumnCount() {
return cols;
}
#Override
public String getColumnName(int col) {
try {
return meta.getColumnLabel(col + 1);
} catch (SQLException e) {
return e.toString();
}
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return String.class;
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
try {
if (!rs.absolute(rowIndex + 1)) {
return null;
}
rs.absolute(rowIndex + 1);
Object o = rs.getObject(columnIndex + 1);
if (o == null) {
return null;
} else {
return o.toString();
}
} catch (SQLException e) {
e.printStackTrace();
return e.toString();
}
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
}
#Override
public void addTableModelListener(TableModelListener l) {
}
#Override
public void removeTableModelListener(TableModelListener l) {
}
}
con = DriverManager.getConnection(url);
st = con.prepareStatement("SELECT id,name,sex,age,cell FROM PATIENTS");
rs = st.executeQuery();
crs = new CachedRowSetImpl();
crs.setType(ResultSet.TYPE_SCROLL_SENSITIVE);
crs.setConcurrency(ResultSet.CONCUR_UPDATABLE);
crs.populate(rs);
tm is the tableModel.
The table will refresh immediately after a row deleted from the cachedRowSet, but when i insert a new row into cachedRowSet, then the table can't show the newly added row immediately. And i checked the rowChanged() been called and the row inserted inside the db.
Even tried to refetch the table data each time or repaint() still not working. I couldn't figure out why.
Maybe cause swing process racing then it can't refresh immediately? I just opened another JFrame to fill out the data and then insert.
Also, what if i use the resultSet directly inside the model? Will the table automatically updated when you insert a row in the db if i didn't close the connection. Or it's just used to get the initial data and you have to run query again to refresh.
Thank you
=================update==================
I tried to change the table model to use ArrayList to store and update db results, then the insert will be update the table immediately. Maybe cause cachedRowSet update slower?
Confused, don't know why.

Java ResultSetTableModel resultset is closed

Reworded this question as it wasn't very clear. My issue is that whenever the generateReport method trys to use model.getColumnCount() its returning zero and giving a ResultSet is Closed error.
However if I remove that finally block, everything works as expected. How do I do this correctly with closing off the connection?
Am I right in thinking that the model only lives within the createTable method as I've used
model = new ResultSetTableModel(rs);
Even though I declared the model as a class variable?
Method that creates the JTable
private void createTable() {
databaseName = (txtQueryDatabase.getText());
String sql = txtQueryString.getText();
openDatabase();
try {
ResultSet rs = stmt.executeQuery(sql);
model = new ResultSetTableModel(rs);
tblEmployee.setModel(model);
txtQueryCount.setText(Integer.toString(model.getRowCount()));
} catch (SQLException e) {
errorMessage(e);
} catch (Exception e) {
errorMessage(e);
} finally {
closeDatabase();
}
The method that writes the file
private void generateReport(File file) throws IOException {
file.createNewFile();
BufferedWriter bfw = new BufferedWriter(new FileWriter(file));
for (int i = 0; i < model.getColumnCount(); i++) {
bfw.write(model.getColumnName(i));
bfw.write(" | ");
}
for (int i = 0; i < model.getRowCount(); i++) {
bfw.newLine();
for (int j = 0; j < model.getColumnCount(); j++) {
bfw.write(model.getValueAt(i, j).toString());
bfw.write(" | ");
}
}
bfw.close();
}
ResultSetTableModel class
public ResultSetTableModel(ResultSet aResultSet) {
try {
rs = aResultSet;
rsmd = rs.getMetaData();
data = new ArrayList<Object>();
while (rs.next()) {
Object[] row = new Object[rsmd.getColumnCount()];
for (int i = 0; i < row.length; i++) {
row[i] = rs.getObject(i + 1);
}
data.add(row);
}
} catch (SQLException e) {
message.errorMessage(e);
}
}
#Override
public Object getValueAt(int row, int col) {
if (row < data.size()) {
return ((Object[]) data.get(row))[col];
} else {
return null;
}
}
#Override
public int getRowCount() {
return data.size();
}
#Override
public String getColumnName(int count) {
try {
return rsmd.getColumnName(++count);
} catch (SQLException e) {
message.errorMessage(e);
return "";
}
}
#Override
public int getColumnCount() {
try {
return rsmd.getColumnCount();
} catch (SQLException e) {
message.errorMessage(e);
return 0;
}
}
}

Categories