1

I currently have 2 classes, one displaying the GUI and one is to get items from the database. My code is as follows:

This code is to display the JTable in my GUI

public void table() {
    if(SOMR.tableCall() == true) {
        this.columnNames = SOMR.getCol();
        this.data = SOMR.getData();
    JTable table = new JTable(data, columnNames)
    {
        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;
        }
    };

    JScrollPane scrollPane = new JScrollPane( table );
    add( scrollPane, BorderLayout.CENTER );
    }

}

and this code is to retrieve the items and pass them to the above codes to display the items retrieved to the JTable

public boolean table() {

    Connection connection = null;  
     ResultSet resultSet = null;  
     PreparedStatement preparedStatement = null;  
     try 
     {  
         Class.forName("org.sqlite.JDBC");  
         connection = DriverManager.getConnection("jdbc:sqlite:db");
         preparedStatement = connection.prepareStatement("SELECT item1, item2, item3 FROM menu WHERE can = ? AND id = ?");
         preparedStatement.setInt(1, can);
         preparedStatement.setInt(2, id);
         resultSet =  preparedStatement.executeQuery();
         ResultSetMetaData md = resultSet.getMetaData();
         columns = 3;//md.getColumnCount();
         for(int i = 1; i<=columns; i++) {
             columnNames.addElement(md.getColumnName(i));
         }
         while(resultSet.next()) {
             row = new Vector(columns);
             for (int i = 1; i<=columns; i++) {
                 row.addElement(resultSet.getObject(i));
             }
             data.addElement(row);
         }
         tablecall = true;
         return tablecall;
     }
     catch (Exception ex) 
     {  
         tablecall = false;
         ex.printStackTrace();  
     }
     finally 
     {  
         try 
         {  
             resultSet.close();  
             preparedStatement.close();  
             connection.close();  
         } 
         catch (Exception ex) 
         {  
             ex.printStackTrace();  
         }  
     }
    return tablecall;
}

I have followed the way of displaying the JTable from Table From Database, however I do not really know how to go about inserting, updating and deleting a row from the JTable and update in the database, then refresh the JTable to display from the newly updated database.

I would like to add an 'add item' button, then it will popup a frame/window with fields to enter, then after clicking 'add' in the popup frame, the JTable and the database will be updated at the same time.

Could anyone please help me in this? I'm lost.. Thank you very much!

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
user1321096
  • 143
  • 3
  • 14
  • most of the part of your code is not making much sense to me. Your first Table displaying code has function `public void table()` and again your data retrieval code function `public boolean table()`. What is `columndName`, what is `row` ? – Sage Nov 03 '13 at 15:56
  • it's just sort of like a class from control class and entity class. The point is I have no idea how to add and update items to the database that will reflect dynamically/immediately to the JTable – user1321096 Nov 03 '13 at 16:06

1 Answers1

3

I am still unclear about your requirements, but lets start answering as much as i have got to:

Every JTable object uses a table model object to manage the actual table data. A table model object must implement the TableModel interface. However the DefaultTableModel it self is enough to work with table data interaction. Check out it's java doc for more details.

However, To detect changes to the data managed by a table model object, the model associating with JTable instance needs to get registered to an implementation of TableModelListener interface using addTableModelListener() function. The listener will be notified with an event TableModelEvent e to inspect the changes in data rows and the type of changes using:

  • e.getFirstRow(): Return the index of the first row that changed, including the table header which is specified by TableModelEvent.HEADER_ROW
  • e.getLastRow(): The last row that changed
  • e.getType(): What happened to the changed cells:
    1. If data rows inserted: e.getType() == TableModelEvent.INSERT
    2. If data rows deleted: e.getType() == TableModelEvent.DELETE
    3. If data rows updated: e.getType() == TableModelEvent.UPDATE.

A Short example:

model.addTableModelListener(new TableModelListener() {

     @Override
     public void tableChanged(TableModelEvent e) {
          int rowFirstIndex = e.getFirstRow();
          int rowLastIndex = e.getLastRow();

          DefaultTableModel model = (DefaultTableModel) e.getSource();
           if(e.getType()==TableModelEvent.UPDATE)
            {
                int updatedColIndex = e.getColumn();
                String updateColmn = table.getColumnName(updatedColIndex);
                String updatedValue = (String) model.getValueAt(rowFirstIndex, updatedColIndex);
                System.out.println("column: "+updateColmn+" value: "+updatedValue);
                updateDB(updateColmn, updatedValue);
            }

            else if(e.getType()==TableModelEvent.INSERT)
            {
             for(int i= rowFirstIndex; i <= rowLastIndex ; i++)  
              {   
                  Vector rowData = (Vector) model.getDataVector().get(i);

                  Map<String, String>dataMap = new HashMap<>();

                  for(int j=0; j < rowData.size() ; j++)
                    dataMap.put(table.getColumnName(j), (String) rowData.get(j));

                  InsertToDB(dataMap); // now it contains columndName corresponding to row value

              }
          }
         }
     });

Edit (on per your comment) : I am getting [value1, value2, value3]. How do I then use this with my SQL statement?

If you are interested to map the row value with column name, as is the case for building SQL query syntax: the vector contains the row data with maintaining column index. That is the row.get(i) has the data with column index i. You can use table.getColumnName(i) to get the name of the column at index i corresponding to the row vector value at index i.

Tutorial:

  1. How to write a table model listener
Sage
  • 15,290
  • 3
  • 33
  • 38
  • I finally got what you meant. But how do I then execute the insert or update statement with "insertToDB(model.getDataVector().get(i));"? Because with this sentence, I am getting [value1, value2, value3]. How do I then use this with my SQL statement? Please help!! Thank you so much! – user1321096 Nov 04 '13 at 17:13
  • @user1321096, you can map the column name with returned vector value by their index as indicated in the answer with `Edit` section. – Sage Nov 04 '13 at 17:34
  • But how do I actually do that? I am passing model.getDataVector().get(i) back to my database class, how do I update using this as per, to the column? – user1321096 Nov 04 '13 at 17:40
  • @user1321096, don't pass `model.getDataVector().get(i)` then. Rather call `insertDB` function with a `HashMap`. You should be able to do it now to map the value and column name. :) let me know – Sage Nov 04 '13 at 17:43
  • because the program is dynamic, and different account uses the same table that stores all the items. Therefore, I don't think passing the column name is a good choice? I'm so confused right now lol. – user1321096 Nov 04 '13 at 17:53
  • @user1321096, if you don't need specific column name then don't. But it is not a bad practice. Updated the answer: check the code of building the `map` from table `vector` row – Sage Nov 04 '13 at 17:59
  • This is getting way too complicated... I am getting more and more confused. What I meant was, with model.getDataVector().get(i), how do I execute the update in the database using SQL statement? – user1321096 Nov 04 '13 at 18:03
  • Sorry, but would you or is there a better way to do this? Is using JTable with Vector the best way to display items off a database? I would really like to keep it simple... – user1321096 Nov 04 '13 at 18:04
  • @user1321096, It is really simple. Keep your head cool. Imagine the table as your own DB table. The table has an unique id(primary key). As i have indicated how to write an insert function, you can write same way an update function just checking the event with `e.getType()==TableModelEvent.UPDATE`. Now you have he vector with data, so in your sql query with the built `map` from the vector you have column name and data. Now in your sql update query, `set` all the `value` corresponding to each `column` *where*, id = `primary key column` – Sage Nov 04 '13 at 18:09
  • @user1321096, i have updated the code with a sample update event and column update fetching. – Sage Nov 04 '13 at 18:35
  • easiest is to override setValueAt, output should be a new Runnable#Thread or SwingWorker that playing with stars on the sky – mKorbel Nov 04 '13 at 19:40
  • @mKorbel, but that will be just another part of his question. Waiting for him to ask as soon as he will stuck on FREEZE ;) and overriding `setValueAt()` would be a good option but to track the *event type and do things on event(insert, update, delete)* it is important to use the listener. – Sage Nov 04 '13 at 19:52
  • @sage so I connect to my database doing this normally without using vector: preparedStatement = connection.prepareStatement("UPDATE table1 set item1 = ?, item2 = ?, item3 = ? WHERE fid = ?"); preparedStatement.setString(1, item1); preparedStatement.setString(2, item2); preparedStatement.setInt(3, item3); preparedStatement.setInt(4, fid); preparedStatement.executeUpdate(); What I don't get is how to convert all these update statements to using vector. – user1321096 Nov 05 '13 at 03:15
  • @user1321096, what have you tried until now ? I have already showed you how to get a updated column with value, i have showed you to get inserted row and convert `vector` into `map`; `map` is the proper way to be used for inserting in DB. did you use google or other means to look for inserting data from a `HashMap` ? – Sage Nov 05 '13 at 05:09
  • I have managed to print the things to be updated. But I have no idea how to pass them back to the database. As in, I do not know how to execute the SQL statement. – user1321096 Nov 05 '13 at 05:19
  • @Sage, I managed to get the update part working. Thank you so much for your guidance. :) One thing may I ask, how do I make use popup to do the insert of data since I'd like my GUI to popup another frame to ask for user input to the database and as well as the JTable? Thank you! – user1321096 Nov 05 '13 at 17:40
  • @user1321096, it is better if you ask another question with a description and of possible with adding a picture. Because, what you are asking may need a brief discussion. One more thing, though i think you know, the common use of this site is to accept the answer if you think it satisfies your question. well as you are not accepting my answer, i guess my answer wasn't satisfactory to you :) – Sage Nov 05 '13 at 17:43
  • @Sage, sorry! Overlooked that! Thought I already marked it as an answer :D – user1321096 Nov 05 '13 at 17:46
  • @user1321096, post another question regarding the popup issue. I and other user will try to answer the question. – Sage Nov 05 '13 at 17:47