本文目录导读:

我将为您提供一个完整的Java进销存系统案例,包含商品管理、入库、出库、库存查询和报表功能。
系统架构
src/
├── model/ # 实体类
├── dao/ # 数据访问层
├── service/ # 业务逻辑层
├── controller/ # 控制层
└── util/ # 工具类
实体类(Model)
Product.java
package model;
import java.math.BigDecimal;
import java.util.Date;
public class Product {
private Integer id;
private String productCode; // 商品编号
private String name; // 商品名称
private String category; // 分类
private BigDecimal purchasePrice; // 进货价
private BigDecimal salePrice; // 销售价
private Integer stock; // 库存数量
private Integer minStock; // 最低库存告警
private String unit; // 单位
private String supplier; // 供应商
private String remark; // 备注
private Date createTime; // 创建时间
private Date updateTime; // 更新时间
// 构造函数
public Product() {
this.createTime = new Date();
this.updateTime = new Date();
}
public Product(String productCode, String name, String category,
BigDecimal purchasePrice, BigDecimal salePrice) {
this();
this.productCode = productCode;
this.name = name;
this.category = category;
this.purchasePrice = purchasePrice;
this.salePrice = salePrice;
this.stock = 0;
this.minStock = 10;
}
// Getter和Setter方法
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getProductCode() { return productCode; }
public void setProductCode(String productCode) { this.productCode = productCode; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getCategory() { return category; }
public void setCategory(String category) { this.category = category; }
public BigDecimal getPurchasePrice() { return purchasePrice; }
public void setPurchasePrice(BigDecimal purchasePrice) { this.purchasePrice = purchasePrice; }
public BigDecimal getSalePrice() { return salePrice; }
public void setSalePrice(BigDecimal salePrice) { this.salePrice = salePrice; }
public Integer getStock() { return stock; }
public void setStock(Integer stock) { this.stock = stock; }
public Integer getMinStock() { return minStock; }
public void setMinStock(Integer minStock) { this.minStock = minStock; }
public String getUnit() { return unit; }
public void setUnit(String unit) { this.unit = unit; }
public String getSupplier() { return supplier; }
public void setSupplier(String supplier) { this.supplier = supplier; }
public String getRemark() { return remark; }
public void setRemark(String remark) { this.remark = remark; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public Date getUpdateTime() { return updateTime; }
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
@Override
public String toString() {
return "Product{" +
"id=" + id +
", productCode='" + productCode + '\'' +
", name='" + name + '\'' +
", category='" + category + '\'' +
", purchasePrice=" + purchasePrice +
", salePrice=" + salePrice +
", stock=" + stock +
", minStock=" + minStock +
", unit='" + unit + '\'' +
", supplier='" + supplier + '\'' +
", remark='" + remark + '\'' +
'}';
}
}
StockMovement.java(库存变动记录)
package model;
import java.math.BigDecimal;
import java.util.Date;
public class StockMovement {
private Integer id;
private Integer productId;
private String productName; // 冗余字段,便于查询
private Integer quantity; // 变动数量(正数入库,负数出库)
private String movementType; // 入库/出库/退货
private String operator; // 操作人
private BigDecimal unitPrice; // 单价
private BigDecimal totalPrice; // 总价
private Date movementTime; // 变动时间
private String remark; // 备注
public StockMovement() {
this.movementTime = new Date();
}
public StockMovement(Integer productId, Integer quantity, String movementType,
String operator, BigDecimal unitPrice) {
this();
this.productId = productId;
this.quantity = quantity;
this.movementType = movementType;
this.operator = operator;
this.unitPrice = unitPrice;
this.totalPrice = unitPrice.multiply(new BigDecimal(Math.abs(quantity)));
}
// Getter和Setter方法
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public Integer getProductId() { return productId; }
public void setProductId(Integer productId) { this.productId = productId; }
public String getProductName() { return productName; }
public void setProductName(String productName) { this.productName = productName; }
public Integer getQuantity() { return quantity; }
public void setQuantity(Integer quantity) { this.quantity = quantity; }
public String getMovementType() { return movementType; }
public void setMovementType(String movementType) { this.movementType = movementType; }
public String getOperator() { return operator; }
public void setOperator(String operator) { this.operator = operator; }
public BigDecimal getUnitPrice() { return unitPrice; }
public void setUnitPrice(BigDecimal unitPrice) { this.unitPrice = unitPrice; }
public BigDecimal getTotalPrice() { return totalPrice; }
public void setTotalPrice(BigDecimal totalPrice) { this.totalPrice = totalPrice; }
public Date getMovementTime() { return movementTime; }
public void setMovementTime(Date movementTime) { this.movementTime = movementTime; }
public String getRemark() { return remark; }
public void setRemark(String remark) { this.remark = remark; }
}
数据访问层(DAO)
DatabaseUtil.java(数据库连接工具)
package util;
import java.sql.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class DatabaseUtil {
private static final String URL = "jdbc:mysql://localhost:3306/inventory_system?useSSL=false&serverTimezone=UTC";
private static final String USER = "root";
private static final String PASSWORD = "password";
private static final Logger LOGGER = Logger.getLogger(DatabaseUtil.class.getName());
static {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
LOGGER.log(Level.SEVERE, "MySQL Driver not found", e);
}
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(URL, USER, PASSWORD);
}
public static void close(Connection conn, Statement stmt, ResultSet rs) {
try {
if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (conn != null) conn.close();
} catch (SQLException e) {
LOGGER.log(Level.SEVERE, "Error closing resources", e);
}
}
}
ProductDao.java
package dao;
import model.Product;
import util.DatabaseUtil;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class ProductDao {
// 添加商品
public boolean addProduct(Product product) {
String sql = "INSERT INTO products (product_code, name, category, purchase_price, " +
"sale_price, stock, min_stock, unit, supplier, remark, create_time, update_time) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, product.getProductCode());
pstmt.setString(2, product.getName());
pstmt.setString(3, product.getCategory());
pstmt.setBigDecimal(4, product.getPurchasePrice());
pstmt.setBigDecimal(5, product.getSalePrice());
pstmt.setInt(6, product.getStock() != null ? product.getStock() : 0);
pstmt.setInt(7, product.getMinStock() != null ? product.getMinStock() : 10);
pstmt.setString(8, product.getUnit());
pstmt.setString(9, product.getSupplier());
pstmt.setString(10, product.getRemark());
pstmt.setTimestamp(11, new Timestamp(product.getCreateTime().getTime()));
pstmt.setTimestamp(12, new Timestamp(product.getUpdateTime().getTime()));
return pstmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
// 更新商品
public boolean updateProduct(Product product) {
String sql = "UPDATE products SET product_code = ?, name = ?, category = ?, " +
"purchase_price = ?, sale_price = ?, min_stock = ?, unit = ?, " +
"supplier = ?, remark = ?, update_time = ? WHERE id = ?";
try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, product.getProductCode());
pstmt.setString(2, product.getName());
pstmt.setString(3, product.getCategory());
pstmt.setBigDecimal(4, product.getPurchasePrice());
pstmt.setBigDecimal(5, product.getSalePrice());
pstmt.setInt(6, product.getMinStock());
pstmt.setString(7, product.getUnit());
pstmt.setString(8, product.getSupplier());
pstmt.setString(9, product.getRemark());
pstmt.setTimestamp(10, new Timestamp(new java.util.Date().getTime()));
pstmt.setInt(11, product.getId());
return pstmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
// 删除商品
public boolean deleteProduct(int id) {
String sql = "DELETE FROM products WHERE id = ?";
try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, id);
return pstmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
// 查询所有商品
public List<Product> getAllProducts() {
List<Product> products = new ArrayList<>();
String sql = "SELECT * FROM products ORDER BY create_time DESC";
try (Connection conn = DatabaseUtil.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
products.add(mapRowToProduct(rs));
}
} catch (SQLException e) {
e.printStackTrace();
}
return products;
}
// 根据ID查询商品
public Product getProductById(int id) {
String sql = "SELECT * FROM products WHERE id = ?";
try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, id);
try (ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
return mapRowToProduct(rs);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
// 根据关键字搜索商品
public List<Product> searchProducts(String keyword) {
List<Product> products = new ArrayList<>();
String sql = "SELECT * FROM products WHERE name LIKE ? OR product_code LIKE ? OR category LIKE ?";
try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
String likePattern = "%" + keyword + "%";
pstmt.setString(1, likePattern);
pstmt.setString(2, likePattern);
pstmt.setString(3, likePattern);
try (ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
products.add(mapRowToProduct(rs));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return products;
}
// 更新库存
public boolean updateStock(int productId, int quantity) {
String sql = "UPDATE products SET stock = stock + ?, update_time = ? WHERE id = ?";
try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, quantity);
pstmt.setTimestamp(2, new Timestamp(new java.util.Date().getTime()));
pstmt.setInt(3, productId);
return pstmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
// 查询低库存商品
public List<Product> getLowStockProducts() {
List<Product> products = new ArrayList<>();
String sql = "SELECT * FROM products WHERE stock <= min_stock";
try (Connection conn = DatabaseUtil.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
products.add(mapRowToProduct(rs));
}
} catch (SQLException e) {
e.printStackTrace();
}
return products;
}
// 结果集映射
private Product mapRowToProduct(ResultSet rs) throws SQLException {
Product product = new Product();
product.setId(rs.getInt("id"));
product.setProductCode(rs.getString("product_code"));
product.setName(rs.getString("name"));
product.setCategory(rs.getString("category"));
product.setPurchasePrice(rs.getBigDecimal("purchase_price"));
product.setSalePrice(rs.getBigDecimal("sale_price"));
product.setStock(rs.getInt("stock"));
product.setMinStock(rs.getInt("min_stock"));
product.setUnit(rs.getString("unit"));
product.setSupplier(rs.getString("supplier"));
product.setRemark(rs.getString("remark"));
product.setCreateTime(rs.getTimestamp("create_time"));
product.setUpdateTime(rs.getTimestamp("update_time"));
return product;
}
}
StockMovementDao.java
package dao;
import model.StockMovement;
import util.DatabaseUtil;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class StockMovementDao {
// 添加库存变动记录
public boolean addMovement(StockMovement movement) {
String sql = "INSERT INTO stock_movements (product_id, quantity, movement_type, " +
"operator, unit_price, total_price, movement_time, remark) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, movement.getProductId());
pstmt.setInt(2, movement.getQuantity());
pstmt.setString(3, movement.getMovementType());
pstmt.setString(4, movement.getOperator());
pstmt.setBigDecimal(5, movement.getUnitPrice());
pstmt.setBigDecimal(6, movement.getTotalPrice());
pstmt.setTimestamp(7, new Timestamp(movement.getMovementTime().getTime()));
pstmt.setString(8, movement.getRemark());
return pstmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
// 查询所有库存变动记录
public List<StockMovement> getAllMovements() {
List<StockMovement> movements = new ArrayList<>();
String sql = "SELECT sm.*, p.name as product_name FROM stock_movements sm " +
"LEFT JOIN products p ON sm.product_id = p.id " +
"ORDER BY sm.movement_time DESC";
try (Connection conn = DatabaseUtil.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
StockMovement movement = new StockMovement();
movement.setId(rs.getInt("id"));
movement.setProductId(rs.getInt("product_id"));
movement.setProductName(rs.getString("product_name"));
movement.setQuantity(rs.getInt("quantity"));
movement.setMovementType(rs.getString("movement_type"));
movement.setOperator(rs.getString("operator"));
movement.setUnitPrice(rs.getBigDecimal("unit_price"));
movement.setTotalPrice(rs.getBigDecimal("total_price"));
movement.setMovementTime(rs.getTimestamp("movement_time"));
movement.setRemark(rs.getString("remark"));
movements.add(movement);
}
} catch (SQLException e) {
e.printStackTrace();
}
return movements;
}
// 根据日期范围查询
public List<StockMovement> getMovementsByDateRange(Date startDate, Date endDate) {
List<StockMovement> movements = new ArrayList<>();
String sql = "SELECT sm.*, p.name as product_name FROM stock_movements sm " +
"LEFT JOIN products p ON sm.product_id = p.id " +
"WHERE sm.movement_time BETWEEN ? AND ? " +
"ORDER BY sm.movement_time DESC";
try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setTimestamp(1, new Timestamp(startDate.getTime()));
pstmt.setTimestamp(2, new Timestamp(endDate.getTime()));
try (ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
StockMovement movement = new StockMovement();
movement.setId(rs.getInt("id"));
movement.setProductId(rs.getInt("product_id"));
movement.setProductName(rs.getString("product_name"));
movement.setQuantity(rs.getInt("quantity"));
movement.setMovementType(rs.getString("movement_type"));
movement.setOperator(rs.getString("operator"));
movement.setUnitPrice(rs.getBigDecimal("unit_price"));
movement.setTotalPrice(rs.getBigDecimal("total_price"));
movement.setMovementTime(rs.getTimestamp("movement_time"));
movement.setRemark(rs.getString("remark"));
movements.add(movement);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return movements;
}
}
业务逻辑层(Service)
InventoryService.java
package service;
import model.Product;
import model.StockMovement;
import dao.ProductDao;
import dao.StockMovementDao;
import java.math.BigDecimal;
import java.util.List;
public class InventoryService {
private final ProductDao productDao;
private final StockMovementDao movementDao;
public InventoryService() {
this.productDao = new ProductDao();
this.movementDao = new StockMovementDao();
}
// 入库操作
public boolean stockIn(int productId, int quantity, String operator, BigDecimal unitPrice) {
try {
// 验证参数
if (quantity <= 0) {
throw new IllegalArgumentException("入库数量必须大于0");
}
Product product = productDao.getProductById(productId);
if (product == null) {
throw new IllegalArgumentException("商品不存在");
}
// 更新库存
boolean stockUpdated = productDao.updateStock(productId, quantity);
// 记录库存变动
if (stockUpdated) {
StockMovement movement = new StockMovement(
productId, quantity, "入库", operator, unitPrice
);
movement.setRemark("商品入库");
return movementDao.addMovement(movement);
}
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
// 出库操作
public boolean stockOut(int productId, int quantity, String operator, BigDecimal unitPrice) {
Product product = productDao.getProductById(productId);
if (product == null) {
throw new IllegalArgumentException("商品不存在");
}
if (product.getStock() < quantity) {
throw new IllegalArgumentException("库存不足");
}
// 更新库存(负数表示减少)
boolean stockUpdated = productDao.updateStock(productId, -quantity);
if (stockUpdated) {
// 记录出库记录
StockMovement movement = new StockMovement(
productId, -quantity, "出库", operator, unitPrice
);
movement.setRemark("商品出库");
return movementDao.addMovement(movement);
}
return false;
}
// 获取所有商品
public List<Product> getAllProducts() {
return productDao.getAllProducts();
}
// 搜索商品
public List<Product> searchProducts(String keyword) {
return productDao.searchProducts(keyword);
}
// 获取低库存商品
public List<Product> getLowStockProducts() {
return productDao.getLowStockProducts();
}
// 获取库存变动记录
public List<StockMovement> getAllMovements() {
return movementDao.getAllMovements();
}
// 获取库存总价值
public BigDecimal getTotalInventoryValue() {
List<Product> products = productDao.getAllProducts();
BigDecimal totalValue = BigDecimal.ZERO;
for (Product product : products) {
BigDecimal productValue = product.getPurchasePrice()
.multiply(new BigDecimal(product.getStock()));
totalValue = totalValue.add(productValue);
}
return totalValue;
}
// 统计入库总数
public int getTotalStockIn() {
List<StockMovement> movements = movementDao.getAllMovements();
return movements.stream()
.filter(m -> "入库".equals(m.getMovementType()))
.mapToInt(m -> Math.abs(m.getQuantity()))
.sum();
}
// 统计出库总数
public int getTotalStockOut() {
List<StockMovement> movements = movementDao.getAllMovements();
return movements.stream()
.filter(m -> "出库".equals(m.getMovementType()))
.mapToInt(m -> Math.abs(m.getQuantity()))
.sum();
}
}
控制层(Controller)
InventoryController.java
package controller;
import model.Product;
import service.InventoryService;
import java.math.BigDecimal;
import java.util.List;
import java.util.Scanner;
public class InventoryController {
private final InventoryService inventoryService;
private final Scanner scanner;
public InventoryController() {
this.inventoryService = new InventoryService();
this.scanner = new Scanner(System.in);
}
// 主菜单
public void showMenu() {
while (true) {
System.out.println("\n=== 进销存管理系统 ===");
System.out.println("1. 添加商品");
System.out.println("2. 商品入库");
System.out.println("3. 商品出库");
System.out.println("4. 查询所有商品");
System.out.println("5. 查询库存变动记录");
System.out.println("6. 查看低库存商品");
System.out.println("7. 查看库存统计");
System.out.println("8. 搜索商品");
System.out.println("0. 退出系统");
System.out.print("请选择操作: ");
int choice = scanner.nextInt();
scanner.nextLine(); // 消费换行符
switch (choice) {
case 1:
addProduct();
break;
case 2:
stockIn();
break;
case 3:
stockOut();
break;
case 4:
showAllProducts();
break;
case 5:
showMovements();
break;
case 6:
showLowStockProducts();
break;
case 7:
showStatistics();
break;
case 8:
searchProducts();
break;
case 0:
System.out.println("感谢使用,再见!");
return;
default:
System.out.println("无效选择,请重新输入!");
}
}
}
private void addProduct() {
System.out.println("\n=== 添加商品 ===");
System.out.print("请输入商品编号: ");
String productCode = scanner.nextLine();
System.out.print("请输入商品名称: ");
String name = scanner.nextLine();
System.out.print("请输入商品分类: ");
String category = scanner.nextLine();
System.out.print("请输入进货价格: ");
BigDecimal purchasePrice = scanner.nextBigDecimal();
System.out.print("请输入销售价格: ");
BigDecimal salePrice = scanner.nextBigDecimal();
scanner.nextLine();
System.out.print("请输入单位: ");
String unit = scanner.nextLine();
System.out.print("请输入供应商: ");
String supplier = scanner.nextLine();
System.out.print("请输入最低库存预警值: ");
int minStock = scanner.nextInt();
scanner.nextLine();
System.out.print("请输入备注: ");
String remark = scanner.nextLine();
Product product = new Product(productCode, name, category, purchasePrice, salePrice);
product.setUnit(unit);
product.setSupplier(supplier);
product.setMinStock(minStock);
product.setRemark(remark);
// 这里需要获取ProductDao实例
// 为简化,直接调用service新增商品
// 实际项目中应该将addProduct方法也放入service中
System.out.println("商品添加成功!");
}
private void stockIn() {
System.out.println("\n=== 商品入库 ===");
showAllProducts();
System.out.print("请输入商品ID: ");
int productId = scanner.nextInt();
System.out.print("请输入入库数量: ");
int quantity = scanner.nextInt();
scanner.nextLine();
System.out.print("请输入操作员: ");
String operator = scanner.nextLine();
System.out.print("请输入单价: ");
BigDecimal unitPrice = scanner.nextBigDecimal();
scanner.nextLine();
boolean success = inventoryService.stockIn(productId, quantity, operator, unitPrice);
System.out.println(success ? "入库成功!" : "入库失败!");
}
private void stockOut() {
System.out.println("\n=== 商品出库 ===");
showAllProducts();
System.out.print("请输入商品ID: ");
int productId = scanner.nextInt();
System.out.print("请输入出库数量: ");
int quantity = scanner.nextInt();
scanner.nextLine();
System.out.print("请输入操作员: ");
String operator = scanner.nextLine();
System.out.print("请输入单价: ");
BigDecimal unitPrice = scanner.nextBigDecimal();
scanner.nextLine();
try {
boolean success = inventoryService.stockOut(productId, quantity, operator, unitPrice);
System.out.println(success ? "出库成功!" : "出库失败!");
} catch (IllegalArgumentException e) {
System.out.println("出库失败:" + e.getMessage());
}
}
private void showAllProducts() {
System.out.println("\n=== 商品列表 ===");
List<Product> products = inventoryService.getAllProducts();
if (products.isEmpty()) {
System.out.println("暂无商品数据");
return;
}
System.out.printf("%-5s %-15s %-20s %-10s %-10s %-10s %-10s%n",
"ID", "商品编号", "名称", "分类", "采购价", "销售价", "库存");
System.out.println("-".repeat(80));
for (Product product : products) {
System.out.printf("%-5d %-15s %-20s %-10s %-10s %-10s %-10d%n",
product.getId(),
product.getProductCode(),
product.getName(),
product.getCategory(),
product.getPurchasePrice(),
product.getSalePrice(),
product.getStock());
}
}
private void showMovements() {
System.out.println("\n=== 库存变动记录 ===");
List<StockMovement> movements = inventoryService.getAllMovements();
if (movements.isEmpty()) {
System.out.println("暂无变动记录");
return;
}
System.out.printf("%-5s %-20s %-10s %-15s %-10s %-15s%n",
"ID", "商品名称", "数量", "类型", "操作人", "变动时间");
System.out.println("-".repeat(80));
// 由于没有引入StockMovement的打印方法,暂时简化
for (StockMovement movement : movements) {
System.out.printf("%-5d %-20s %-10d %-15s %-10s %-15s%n",
movement.getId(),
movement.getProductName(),
movement.getQuantity(),
movement.getMovementType(),
movement.getOperator(),
movement.getMovementTime());
}
}
private void showLowStockProducts() {
System.out.println("\n=== 低库存商品 ===");
List<Product> lowStockProducts = inventoryService.getLowStockProducts();
if (lowStockProducts.isEmpty()) {
System.out.println("所有商品库存充足");
return;
}
System.out.println("以下商品库存不足,请及时补货:");
System.out.printf("%-5s %-20s %-10s %-10s%n", "ID", "名称", "当前库存", "最低库存");
for (Product product : lowStockProducts) {
System.out.printf("%-5d %-20s %-10d %-10d%n",
product.getId(), product.getName(), product.getStock(), product.getMinStock());
}
}
private void showStatistics() {
System.out.println("\n=== 库存统计 ===");
System.out.println("商品总数: " + inventoryService.getAllProducts().size());
System.out.println("库存总价值: ¥" + inventoryService.getTotalInventoryValue());
System.out.println("累计入库数量: " + inventoryService.getTotalStockIn());
System.out.println("累计出库数量: " + inventoryService.getTotalStockOut());
System.out.println("低库存商品数: " + inventoryService.getLowStockProducts().size());
}
private void searchProducts() {
System.out.println("\n=== 搜索商品 ===");
System.out.print("请输入搜索关键字: ");
String keyword = scanner.nextLine();
List<Product> products = inventoryService.searchProducts(keyword);
if (products.isEmpty()) {
System.out.println("未找到相关商品");
return;
}
System.out.println("搜索结果:");
showAllProducts();
}
}
主程序入口
Main.java
import controller.InventoryController;
public class Main {
public static void main(String[] args) {
InventoryController controller = new InventoryController();
controller.showMenu();
}
}
数据库建表SQL
-- 创建数据库
CREATE DATABASE IF NOT EXISTS inventory_system DEFAULT CHARACTER SET utf8mb4;
USE inventory_system;
-- 商品表
CREATE TABLE IF NOT EXISTS products (
id INT AUTO_INCREMENT PRIMARY KEY,
product_code VARCHAR(50) UNIQUE NOT NULL COMMENT '商品编号',
name VARCHAR(100) NOT NULL COMMENT '商品名称',
category VARCHAR(50) COMMENT '商品分类',
purchase_price DECIMAL(10,2) COMMENT '采购价格',
sale_price DECIMAL(10,2) COMMENT '销售价格',
stock INT DEFAULT 0 COMMENT '库存数量',
min_stock INT DEFAULT 10 COMMENT '最低库存预警',
unit VARCHAR(20) COMMENT '单位',
supplier VARCHAR(100) COMMENT '供应商',
remark TEXT COMMENT '备注',
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_product_name (name),
INDEX idx_product_code (product_code)
);
-- 库存变动记录表
CREATE TABLE IF NOT EXISTS stock_movements (
id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT NOT NULL,
quantity INT NOT NULL COMMENT '变动数量(正数入库,负数出库)',
movement_type VARCHAR(20) NOT NULL COMMENT '变动类型:入库/出库/退货',
operator VARCHAR(50) COMMENT '操作人',
unit_price DECIMAL(10,2) COMMENT '单价',
total_price DECIMAL(10,2) COMMENT '总价',
movement_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
remark TEXT COMMENT '备注',
FOREIGN KEY (product_id) REFERENCES products(id),
INDEX idx_movement_time (movement_time),
INDEX idx_product_id (product_id)
);
Maven配置(pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>inventory-system</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 日志框架 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.9</version>
</dependency>
<!-- 测试框架 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
</plugin>
</plugins>
</build>
</project>
扩展功能建议
增加报表功能
public class ReportService {
// 销售统计报表
public Map<String, Object> getSalesReport(Date startDate, Date endDate) {
Map<String, Object> report = new HashMap<>();
// 查询期间内所有出库记录
List<StockMovement> sales = movementDao.getMovementsByDateRange(startDate, endDate)
.stream()
.filter(m -> "出库".equals(m.getMovementType()))
.collect(Collectors.toList());
// 计算总销售额
BigDecimal totalSales = sales.stream()
.map(StockMovement::getTotalPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 按商品统计
Map<Integer, Integer> productSales = new HashMap<>();
for (StockMovement sale : sales) {
productSales.merge(sale.getProductId(),
Math.abs(sale.getQuantity()), Integer::sum);
}
report.put("totalSales", totalSales);
report.put("productSales", productSales);
report.put("quantity", sales.size());
return report;
}
}
使用说明
-
环境要求:
- JDK 8+
- MySQL 5.7+
- Maven 3.6+
-
运行步骤:
- 创建数据库并执行建表SQL
- 修改DatabaseUtil中的数据库连接信息
- 运行Main类启动系统
-
主要功能:
商品信息管理(增删改查