你的代码有点倾斜,你有一个Stock
对象,但该对象似乎也在管理数据库,作为一个更长期的解决方案,我建议将这些问题分开,但现在我们暂时保留它。
我要做的第一件事是定义模型的期望,你期望它做什么,你期望它如何工作
public interface MutableStockModel {
public void add(Stock item) throws ModelException;
public void remove(Stock item) throws ModelException;
}
所以这是一个简单的接口,它定义了任何实现类都应该提供的几个操作。但你为什么问?这是个好问题,我很快就会回答。
您可以延长MutableStockModel
from a TableModel
,但这将您锁定在一个特定的实施渠道中,这可能无法满足您的长期需求,此外,使用它的人关心什么,他们只是希望能够添加和删除产品
一个示例实现...
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);
}
}
}
所以这是基本的示例,您的代码都不关心它的实际管理方式,只关心它满足合同要求。
要添加或删除产品,只需调用特定方法即可。
现在,您可以扩展这个概念以使其更易于使用,例如......
public interface MutableStockTableModel extends MutableStockModel, TableModel {
public void removeAt(int row) throws ModelException;
}
这是一个特定的、有针对性的实现,它允许您删除特定行的行。这延伸了TableModel
,因为一个TableModel
有一个“行”的概念,MutableStockModel
没有。当然,您必须更新任何实现implement
这个特定的interface
;)
好吧,但是“为什么”呢?
简短的回答是,根据数据库的不同,ResultSet
实际上可以直接进行变异,也就是说,您可以直接通过ResultSet
, see 从结果集中检索和修改值 https://docs.oracle.com/javase/tutorial/jdbc/basics/retrieving.html更多细节。
这意味着您可以创建一个实现TableModel
它实现了MutableStockTableModel
or MutableStockModel
接口,但引用了原始接口ResultSet
因为它的内部结构。
听起来很简单,但是当您意识到可以更改的任何实例时TableModel
对于任何满足实现要求而不影响任何代码的实现,它开辟了多种可能性。
因此,例如,不要使用TableModel
or DefaultTableModel
在你的代码中,你可以使用
private MutableStockTableModel tableModel;
//...
tableModel = new ResultSetMutableStockTableModel(resultSet);
table.setModel(tableModel);
//...
tableModel.add(stockItem);
但你可以简单地改变tableModel
对于不同的例子...
tableModel = new DefaultStockTableModel(listOfItems);
没有其他需要改变的!
所以,这是“编码到接口,而不是实现”的基本示例,我可以进一步解耦代码,但我不想让你不知所措;)
回到我的第一条评论,OO 提倡单一责任原则 http://www.oodesign.com/single-responsibility-principle.html,这意味着任何对象都应该有单一的职责(或工作)。
例如,这可能建议您应该将您的功能分开Stock
class.
天哪,我会从惊讶开始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();
}
然后你会有某种实施......
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;
}
}
然后你可能会有某种经理/控制器/工厂......
(是的,我很想通过某种界面来描述这一点,但这已经是一篇很长的文章了)
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;
}
}
我也鼓励你看看使用准备好的语句 http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html整体改进代码