JTable Won't populate when clicking JButton

Deadly 提交于 2020-01-11 14:27:11

问题


The system I'm developing is a till system and the JTable acts as the orderList. I've tried Vector and I've tried to use DefaultTableModel but I'm not sure how to make the button pull the data and for it to add to the table. I know that this is quite hard to follow but could anyone maybe show me how I should do it for one JButton and then the rest should be similar, I can do those myself?

I need productID, productName and Price to be pulled from DB and added to table.

I will then total the price and take payment for the order.

Order

//Order class for setting up and managing an order

package classes;

import java.sql.*;
import java.util.ArrayList;
import java.util.Vector;

public class Order 
{
    // Instance Variables
        private int productID;
        private String productName;
        private String productDescription;
        private String type;
        private String supplierName;
        private double quantity;
        private double price;

    // Connection To DB
    // JDBC Driver name and database URL
        final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
        final String DB_URL = "jdbc:mysql://localhost/team_project?useSSL=false";
        final String USER_NAME = "root";
        final String PASSWORD = "password";

        // sql variables
        ResultSet resultSet = null;
        private String itemName;
        private double itemPrice;

    // Constructors
    public Order()
    {

    }

    public Order(int productID, String itemName, double itemPrice, double quantity)
    {
        this.itemName = itemName;
        this.itemPrice = itemPrice;
        this.quantity = quantity;
    }


    // Get the details of stock items and add them to the order
    public Vector getOrderItems()
    {
         ResultSet rs = null;

        Statement statement = null;
        try{

            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
            Statement stmt = conn.createStatement();
            String sqlString= "select ProductID, ProductName, Price from product";
            stmt.executeUpdate(sqlString);  
            Vector vector = new Vector();
            Vector<String> orderItem = new Vector<String>();
            int i=0;
            while(rs.next())
            { 
                Vector<String> items = new Vector<String>();
                rs.getInt("ProductID");
                rs.getString("ProductName");
                rs.getDouble("Price");
            }
            return vector;
            }catch(Exception e)
            {
                e.printStackTrace();
            }
        return null;    
    }


         // Getter Methods
            public int getProductID()
            {
                return productID;
            }

            public String getProductName()                                  
            {
                return productName;
            }

            public String getProductDesc()
            {
                return productDescription;
            }

            public String getType()
            {
                return type;
            }

            public String getSupplierName()
            {
                return supplierName;
            }

            public double getQuantity()
            {
                return quantity;
            }

            public double getPrice()
            {
                return price;
            }
        }

Stock

// Stock class
//Team Project
//Stock class for setting up and managing stock

package classes;

import java.sql.*;
import java.util.*;

public class Stock 
{
    // Instance Variables
    private int productID;
    private String productName;
    private String productDescription;
    private String type;
    private String supplierName;
    private double quantity;
    private double price;




    // JDBC Driver name and database URL
    final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    final String DB_URL = "jdbc:mysql://localhost/team_project?useSSL=false";
    final String USER_NAME = "root";
    final String PASSWORD = "password";


    // sql variables
    Statement statement = null;
    ResultSet resultSet = null;

    public Stock()
    {
        productID=0;
        productName=null;
        productDescription = null;
        type = null;
        supplierName=null;      
        quantity = 0;
        price=0;
    }

    // Initialisation Constructor that initializes everything in DB
    public Stock(int productID, String productName, String productDescription, String type, String supplierName,
                double quantity, double price)
    {
        this.productID = productID;
        this.productName = productName;
        this.productDescription = productDescription;
        this.type = type;
        this.supplierName = supplierName;
        this.quantity = quantity;
        this.price = price;
    }



    // Add a new product into the product table
    public void addProduct(int prodID, int amt) 
    {
        try
        {
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);

            Statement stmt = conn.createStatement();
            String sqlString="insert into product " + "(ProductID, ProductName, ProductDescrp, type, SupplierName, Quantity, Price)"
            + " values(30, 'Marmalade', 'Homestead', 'Extras', 'Bakersworld', 20, 0.20)";
            stmt.executeUpdate(sqlString);
            conn.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    // Delete a product from the product table
    public void delete(int prodNumIn)
    {
        try
        {
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);

            Statement stmt = conn.createStatement();
            String sqlString= "delete from team_Project.product where ProductID=" + prodNumIn;
            stmt.executeUpdate(sqlString);  
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    // Subtracts quantity in stock in the DB When a sale is made on an item
    public int deductStock(int prodID) 
    {
        int status =0;
          String sql = ("UPDATE product " + "SET Quantity = " + (getDBQuantity(prodID)-1) + " WHERE ProductID = " + prodID);
          status = databaseUpdate(sql);
          return status;
    }

    // Add quantity to particular product in the DB if required
    public int addToQuantity(int prodID, int amt) 
    {
        int status =0;
        String sql = ("UPDATE product " + "SET Quantity = " + (getDBQuantity(prodID)+ amt) + " WHERE ProductID = " + prodID);
        status = databaseUpdate(sql);
        return status;

    }

    // return quantity of a product in DB
    public int getDBQuantity(int prodID)
    {
        int quantity=0;
        try
        {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);

        statement = (Statement) conn.createStatement();
        resultSet = statement.executeQuery("select Quantity from team_project.product WHERE ProductID = " + prodID);

        while (resultSet.next())
        {       
            quantity = (resultSet.getInt("Quantity"));
        }
        conn.close();
        }catch(Exception e)
        {
            e.printStackTrace();
        }
        return quantity;
        }


    // get price of a particular product 
    public int getItemPrice(int prodID)
    {
        int price = 0;      

        try{
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);

            statement = (Statement) conn.createStatement();
            resultSet = statement.executeQuery("select Price from team_project.product WHERE ProductID = " + prodID);

        while (resultSet.next())
        {       
            price = (resultSet.getInt("Price"));
        }
        conn.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        System.out.println("€"+price);
        return price;
        }



    // Method that returns all products in product table
    public ArrayList<Stock> getProducts()
    {
        ArrayList<Stock> allStock = new ArrayList<Stock>();

    try
    {
    Class.forName("com.mysql.jdbc.Driver");
    Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);

    statement = (Statement) conn.createStatement();
    resultSet = statement.executeQuery("select * from team_project.product");

    while (resultSet.next())
    {       
        Stock  stock = new Stock(resultSet.getInt("ProductID"), resultSet.getString("ProductName"), 
                resultSet.getString("ProductDescrp"),resultSet.getString("Type"),resultSet.getString("SupplierName"), 
                resultSet.getInt("Quantity"), resultSet.getDouble("Price"));
        allStock.add(stock);
    }
    conn.close();

    }catch(Exception e)
    {
        e.printStackTrace();
    }
    return allStock;
    }

    // update method to call
    // database update method 
         private int databaseUpdate(String sqlUpdate)
         {
              int status = 0;

              try{
                 Class.forName("com.mysql.jdbc.Driver");
                 Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
                 statement = conn.createStatement();
                 status = statement.executeUpdate(sqlUpdate);
                 conn.close(); 
              }       

              catch (Exception e) {
                 e.printStackTrace();
              }   
              return status;
           }

         // toString method for stock items
         public String toString()
         {
             return productName + "";
         }



    // Getter Methods
    public int getProductID()
    {
        return productID;
    }

    public String getProductName()                                  
    {
        return productName;
    }

    public String getProductDesc()
    {
        return productDescription;
    }

    public String getType()
    {
        return type;
    }

    public String getSupplierName()
    {
        return supplierName;
    }

    public double getQuantity()
    {
        return quantity;
    }

    public double getPrice()
    {
        return price;
    }
}

// Small Americano Listener

americanoSmall.addActionListener(
        new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                try {
                    String query = "select ProductName, Price from product where ProductID = 24";
                    java.sql.PreparedStatement pst = connection.prepareStatement(query);
                    ResultSet rs = pst.executeQuery();
                    table.setModel(DbUtils.resultSetToTableModel(rs));

                    } catch (Exception e1) 
                    {
                        e1.printStackTrace();
                    }
                }
            });    

回答1:


You code is a little skewed, you have a Stock object, but that object seems to be also managing the database, as a more long term solution, I would recommend separating those concerns, but for now we'll leave that for the time been.

The first thing I would do is define the expectations of the model, what do you expect it to do, how do you expect it to work

public interface MutableStockModel {
    public void add(Stock item) throws ModelException;
    public void remove(Stock item) throws ModelException;
}

So this is a simple interface which defines a couple of actions which any implementing class is expected to provide. But why you ask? That's a good question I'll answer shortly.

You could extend the MutableStockModel from a TableModel, but that locks you into a particular implementation channel which may not meet your long term needs, besides, what does any one using it care, they just want to be able to add and remove products

An example implementation...

public class DefaultStockTableModel extends AbstractTableModel implements MutableStockModel {

    private List<Stock> items;

    public DefaultStockTableModel() {
        items = new ArrayList<>(25);
    }

    public DefaultStockTableModel(List<Stock> items) {
        this.items = items;
    }

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

    @Override
    public int getColumnCount() {
        return 7;
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
            case 1:
            case 2:
            case 3:
            case 4: return String.class;
            case 0:
            case 5:
            case 7: return int.class;
        }
        return Object.class;
    }

    @Override
    public String getColumnName(int column) {
        switch (column) {
            case 0: return "ID";
            case 1: return "Name";
            case 2: return "Description";
            case 3: return "Type";
            case 4: return "Supplier Name";
            case 5: return "Quanity";
            case 6: return "Price";
        }
        return null;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Stock item = items.get(rowIndex);
        switch (columnIndex) {
            case 0: return item.getProductID();
            case 1: return item.getProductName();
            case 2: return item.getProductDesc();
            case 3: return item.getType();
            case 4: return item.getSupplierName();
            case 5: return item.getQuantity();
            case 6: return item.getPrice();
        }
        return null;
    }

    @Override
    public void add(Stock item) throws ModelException {
        // Add the item to the database if required
        items.add(item);
        int row = items.indexOf(item);
        fireTableRowsInserted(row, row);
    }

    @Override
    public void remove(Stock item) throws ModelException {
        if (items.contains(item)) {
            // Delete theitem from the database if required
            int row = items.indexOf(item);
            items.remove(row);
            fireTableRowsDeleted(row, row);
        }
    }

}

So this is basic example, none of your code cares how it's actually managed, only that it meets the contractual requirements.

To add or remove a product, simply call the specific methods.

Now, you can expand this concept to make it easier to use, for example...

public interface MutableStockTableModel extends MutableStockModel, TableModel {
    public void removeAt(int row) throws ModelException;
}

This is a specific, targeted implementation, which allows you to remove a row at a specific row. This extends TableModel, because a TableModel has a concept of "rows", which the MutableStockModel doesn't. Of course, you'd have to update any implementations implement this particular interface ;)

Okay, but "why"?

The short answer is, depending on the database, the ResultSet can actually be mutated directly, that is, you can add/insert, remove and update rows directly via the ResultSet, see Retrieving and Modifying Values from Result Sets for more details.

This means you could create an implementation of a TableModel which implements the MutableStockTableModel or MutableStockModel interfaces but which took a reference to the original ResultSet as it's internal structure.

Sounds, simple, but when you realise you can change any instance of the TableModel for any implementation which meet the implementation requirements without affecting any of your code, it opens up a swagger of possibilities.

So, for example, instead of using TableModel or DefaultTableModel in your code, you might use

private MutableStockTableModel tableModel;

//...

tableModel = new ResultSetMutableStockTableModel(resultSet);
table.setModel(tableModel);

//...

tableModel.add(stockItem);

But you could simply change the tableModel for a different instance...

tableModel = new DefaultStockTableModel(listOfItems);

and nothing else needs to change!

So, this is basic example of "coding to interface, not implementation" and I could decouple the code further, but I don't want to overwhelm you ;)

Going back to my first comment, OO promotes the Single Responsibility Principle, meaning that any object should have a single responsibility (or job).

This might suggest that, for example, you should separate the functionality of your Stock class.

My, I'd start with, surprise, a interface...

public interface Stock {
    public int getProductID();
    public String getProductName();
    public String getProductDesc();
    public String getType();
    public String getSupplierName();
    public double getQuantity();
    public double getPrice();
}

And then you'd have some kind of implementation...

public class DefaultStock implements Stock {
    // Instance Variables

    private int productID;
    private String productName;
    private String productDescription;
    private String type;
    private String supplierName;
    private double quantity;
    private double price;

    public DefaultStock() {
        productID = 0;
        productName = null;
        productDescription = null;
        type = null;
        supplierName = null;
        quantity = 0;
        price = 0;
    }

    // Initialisation Constructor that initializes everything in DB
    public DefaultStock(int productID, String productName, String productDescription, String type, String supplierName,
                             double quantity, double price) {
        this.productID = productID;
        this.productName = productName;
        this.productDescription = productDescription;
        this.type = type;
        this.supplierName = supplierName;
        this.quantity = quantity;
        this.price = price;
    }

    // toString method for stock items
    @Override
    public String toString() {
        return productName + "";
    }

    // Getter Methods
    @Override
    public int getProductID() {
        return productID;
    }

    @Override
    public String getProductName() {
        return productName;
    }

    @Override
    public String getProductDesc() {
        return productDescription;
    }

    @Override
    public String getType() {
        return type;
    }

    @Override
    public String getSupplierName() {
        return supplierName;
    }

    @Override
    public double getQuantity() {
        return quantity;
    }

    @Override
    public double getPrice() {
        return price;
    }
}

And then you might have some kind of manager/controller/factory...

(And yes, I'd be tempted to describe this through some kind of interface, but this is already a long post)

public class StockManager {

    // JDBC Driver name and database URL
    final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    final String DB_URL = "jdbc:mysql://localhost/team_project?useSSL=false";
    final String USER_NAME = "root";
    final String PASSWORD = "password";

    // sql variables
    Statement statement = null;
    ResultSet resultSet = null;

    // Add a new product into the product table
    public void addProduct(int prodID, int amt) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);

            Statement stmt = conn.createStatement();
            String sqlString = "insert into product " + "(ProductID, ProductName, ProductDescrp, type, SupplierName, Quantity, Price)"
                    + " values(30, 'Marmalade', 'Homestead', 'Extras', 'Bakersworld', 20, 0.20)";
            stmt.executeUpdate(sqlString);
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // Delete a product from the product table
    public void delete(int prodNumIn) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);

            Statement stmt = conn.createStatement();
            String sqlString = "delete from team_Project.product where ProductID=" + prodNumIn;
            stmt.executeUpdate(sqlString);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // Subtracts quantity in stock in the DB When a sale is made on an item
    public int deductStock(int prodID) {
        int status = 0;
        String sql = ("UPDATE product " + "SET Quantity = " + (getDBQuantity(prodID) - 1) + " WHERE ProductID = " + prodID);
        status = databaseUpdate(sql);
        return status;
    }

    // Add quantity to particular product in the DB if required
    public int addToQuantity(int prodID, int amt) {
        int status = 0;
        String sql = ("UPDATE product " + "SET Quantity = " + (getDBQuantity(prodID) + amt) + " WHERE ProductID = " + prodID);
        status = databaseUpdate(sql);
        return status;

    }

    // return quantity of a product in DB
    public int getDBQuantity(int prodID) {
        int quantity = 0;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);

            statement = (Statement) conn.createStatement();
            resultSet = statement.executeQuery("select Quantity from team_project.product WHERE ProductID = " + prodID);

            while (resultSet.next()) {
                quantity = (resultSet.getInt("Quantity"));
            }
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return quantity;
    }

    // get price of a particular product 
    public int getItemPrice(int prodID) {
        int price = 0;

        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);

            statement = (Statement) conn.createStatement();
            resultSet = statement.executeQuery("select Price from team_project.product WHERE ProductID = " + prodID);

            while (resultSet.next()) {
                price = (resultSet.getInt("Price"));
            }
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("€" + price);
        return price;
    }

    // Method that returns all products in product table
    public ArrayList<Stock> getProducts() {
        ArrayList<Stock> allStock = new ArrayList<Stock>();

        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);

            statement = (Statement) conn.createStatement();
            resultSet = statement.executeQuery("select * from team_project.product");

            while (resultSet.next()) {
                Stock stock = new DefaultStock(resultSet.getInt("ProductID"), resultSet.getString("ProductName"),
                                                                resultSet.getString("ProductDescrp"), resultSet.getString("Type"), resultSet.getString("SupplierName"),
                                                                resultSet.getInt("Quantity"), resultSet.getDouble("Price"));
                allStock.add(stock);
            }
            conn.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return allStock;
    }

    // update method to call
    // database update method 
    private int databaseUpdate(String sqlUpdate) {
        int status = 0;

        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
            statement = conn.createStatement();
            status = statement.executeUpdate(sqlUpdate);
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return status;
    }

}

I'd also encourage you to have a look at Using Prepared Statements to improve the code overall




回答2:


Part one

First : When you want to use SELECT you have to use stmt.executeQuery(sqlString); or stmt.execute(sqlString); instead of executeUpdate it used when you want to make a an insert update or delete:

stmt.executeQuery(sqlString);

Second : I think you are missing something in your URL you are missing the port number :

"jdbc:mysql://localhost/team_project?useSSL=false";
//---------------------^--------------------------

It should be like this, the default port of MySQL is 3306:

"jdbc:mysql://localhost:3306/team_project?useSSL=false";

Note using statement is not safe, it can cause a syntax error or SQL Injection, instead i suggest to use PreparedStatement, it is more secure and more helpful

Part two

To populate your JTable i usually use this way :

//call this method to fill your Object in your JTable when you click to your button
private void fillData(List<MY_OBJECT> list) {//method which take a list of objects 

    DefaultTableModel model = (DefaultTableModel) jTableName.getModel();

    // empty your JTable
    model.setRowCount(0);

    //Fill your JTbale
    for (MY_OBJECT obj : list) {
        model.addRow(new Object[]{
            obj.getAttribute1(),
            obj.getAttribute2,
            obj.getAttribute3
        });
    }
}



回答3:


here is a Minimal, Complete, and Verifiable example (MCVE) how to populate the table:

public class TableAddRowButton {

    public static class Order {
        static int idCounter = 0;
        private int productID = ++idCounter;
        private String productName = "Product" + productID;
        private double quantity = new Random().nextInt(1000);
        private double price = new Random().nextInt(1000);
    }

    public static void main(String[] args) {
        Vector<Order> orders = new Vector<>();
        DefaultTableModel tableModel = createTableModel(orders);
        JButton button = createAddRowButton(orders, tableModel);
        JPanel panel = new JPanel(new BorderLayout());
        panel.add(button, BorderLayout.NORTH);
        panel.add(new JScrollPane(new JTable(tableModel)));
        JOptionPane.showMessageDialog(null, panel);

    }

    private static JButton createAddRowButton(Vector<Order> orders, DefaultTableModel tableModel) {
        JButton button = new JButton(new AbstractAction("add row") {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                orders.add(new Order());
                tableModel.fireTableRowsInserted(orders.size() - 2, orders.size() - 1);
            }
        });
        return button;
    }

    private static DefaultTableModel createTableModel(Vector<Order> orders) {
        DefaultTableModel tableModel = new DefaultTableModel(
                new Vector<>(Arrays.asList("ID", "Name", "quantity", "price")), orders.size()) {

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

            @Override
            public Object getValueAt(int row, int column) {
                switch (column) {
                case 0:
                    return orders.get(row).productID;
                case 1:
                    return orders.get(row).productName;
                case 2:
                    return orders.get(row).quantity;
                case 3:
                    return orders.get(row).price;
                default:
                    return "";
                }
            }

            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };
        return tableModel;
    }
}


来源:https://stackoverflow.com/questions/43076871/jtable-wont-populate-when-clicking-jbutton

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!