Java进销存系统案例

wen java案例 2

本文目录导读:

Java进销存系统案例

  1. 系统架构
  2. 实体类(Model)
  3. 数据访问层(DAO)
  4. 业务逻辑层(Service)
  5. 控制层(Controller)
  6. 主程序入口
  7. 数据库建表SQL
  8. Maven配置(pom.xml)
  9. 扩展功能建议
  10. 使用说明

我将为您提供一个完整的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;
    }
}

使用说明

  1. 环境要求

    • JDK 8+
    • MySQL 5.7+
    • Maven 3.6+
  2. 运行步骤

    • 创建数据库并执行建表SQL
    • 修改DatabaseUtil中的数据库连接信息
    • 运行Main类启动系统
  3. 主要功能

    商品信息管理(增删改查

抱歉,评论功能暂时关闭!