1. 项目概述:企业级进销存系统的毕业设计实战
福泰轴承进销存系统是一个典型的制造业ERP子系统,主要解决轴承类产品的采购、销售和库存管理问题。作为计算机专业毕业设计的选题,这个项目完美融合了Java企业级开发的核心技术栈——Spring Boot框架+MySQL数据库,既能展示完整的软件开发流程,又符合企业实际应用场景。
我在指导毕业设计的过程中发现,进销存系统是最能锻炼学生全栈开发能力的选题之一。它要求开发者同时具备后端业务逻辑处理、数据库设计和前端交互实现的能力,而Spring Boot的自动化配置特性恰好能降低技术复杂度,让学生把精力集中在业务逻辑的实现上。
这个系统最核心的价值在于:通过规范化轴承产品的入库、出库和库存预警流程,帮助企业减少人工操作失误,实时掌握库存动态。对于毕业设计而言,它包含了用户权限管理、商品信息CRUD、采购/销售订单处理、库存统计报表等经典模块,完全满足本科毕业设计的创新性和工作量要求。
2. 技术选型与架构设计
2.1 为什么选择Spring Boot+MySQL组合
Spring Boot作为当前Java领域最主流的开发框架,其优势在毕业设计场景中尤为突出:
- 自动配置:省去传统SSH框架复杂的XML配置,starter依赖开箱即用
- 内嵌Tomcat:直接打包成可执行JAR,部署简单到只需
java -jar - Actuator监控:毕业答辩时可以直接展示健康检查、性能指标等数据
MySQL的选用则基于以下考量:
- 事务完整性:InnoDB引擎完美支持采购单、销售单的ACID特性
- 成本优势:社区版完全免费,避免商用数据库的授权问题
- 生态工具:Navicat、Workbench等可视化工具方便调试
2.2 系统分层架构设计
采用经典的三层架构,但针对毕业设计做了适当简化:
code复制表现层:Thymeleaf模板 + Bootstrap5
业务层:Spring MVC + Spring Data JPA
数据层:MySQL 8.0 + Redis缓存(可选)
特别建议在application.yml中做好多环境配置:
yaml复制spring:
profiles:
active: dev
datasource:
url: jdbc:mysql://localhost:3306/bearing_erp?useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
show-sql: true
hibernate:
ddl-auto: update
注意:毕业答辩时务必关闭show-sql,避免控制台刷屏影响演示效果
3. 核心功能模块实现
3.1 商品管理模块
轴承产品需要特殊字段设计:
java复制@Entity
public class BearingProduct {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String skuCode; // 轴承型号如6205-2RS
private String material; // 轴承钢/陶瓷等
private String sealType; // RS/ZZ等密封类型
private Double innerDiameter; // 内径(mm)
private Double outerDiameter; // 外径(mm)
private Integer width; // 宽度(mm)
@Lob
private String specification; // 详细技术参数
}
实现分页查询时推荐使用Spring Data的Pageable:
java复制@GetMapping("/products")
public String listProducts(
@RequestParam(defaultValue = "1") int page,
Model model) {
Pageable pageable = PageRequest.of(page - 1, 10, Sort.by("skuCode"));
Page<BearingProduct> productPage = productRepository.findAll(pageable);
model.addAttribute("page", productPage);
return "product/list";
}
3.2 采购入库流程
采购单需要处理供应商关联和库存更新:
java复制@Transactional
public PurchaseOrder createPurchase(PurchaseForm form) {
// 1. 创建采购单
PurchaseOrder order = new PurchaseOrder();
order.setSupplier(supplierRepo.findById(form.getSupplierId()).orElseThrow());
// 2. 处理采购明细
List<PurchaseItem> items = form.getItems().stream()
.map(item -> {
BearingProduct product = productRepo.findBySkuCode(item.getSkuCode());
product.setStock(product.getStock() + item.getQuantity()); // 更新库存
return new PurchaseItem(product, item.getQuantity());
}).collect(Collectors.toList());
order.setItems(items);
return purchaseRepo.save(order);
}
3.3 库存预警功能
在BearingProduct实体中增加库存阈值字段:
java复制private Integer warningStock; // 预警库存量
@Transient // 非持久化字段
public boolean isLowStock() {
return stock != null && warningStock != null
&& stock < warningStock;
}
定时任务检查库存(每天上午9点执行):
java复制@Scheduled(cron = "0 0 9 * * ?")
public void checkStockWarning() {
List<BearingProduct> lowStockProducts = productRepo
.findByStockLessThanWarningStock();
lowStockProducts.forEach(product -> {
String message = String.format("轴承%s库存不足!当前%d件,预警值%d件",
product.getSkuCode(), product.getStock(), product.getWarningStock());
emailService.sendWarningEmail(message);
});
}
4. 毕业设计特别注意事项
4.1 数据库设计规范
-
命名统一性:
- 表名:t_product / t_purchase_order
- 字段名:product_name / purchase_count
-
索引优化:
sql复制ALTER TABLE t_bearing_product
ADD INDEX idx_sku (sku_code),
ADD INDEX idx_dimension (inner_diameter, outer_diameter);
- 避免使用数据库保留字:
- 错误:
desc→ 正确:description
- 错误:
4.2 答辩演示技巧
- 准备测试数据集:
sql复制INSERT INTO t_bearing_product
(sku_code, material, inner_diameter, outer_diameter, width, stock, warning_stock)
VALUES
('6205-2RS', '轴承钢', 25.0, 52.0, 15, 50, 100),
('6308-ZZ', '轴承钢', 40.0, 90.0, 23, 30, 50);
-
演示路线图:
- 登录 → 新增商品 → 采购入库 → 销售出库 → 查看库存报表
- 触发库存预警 → 展示预警邮件
-
性能优化展示点:
- 对比加索引前后的查询速度
- 演示JPA的二级缓存配置
5. 常见问题解决方案
5.1 MySQL连接问题
错误现象:
code复制Communications link failure
解决方案:
- 检查MySQL服务是否启动
- 确认连接URL时区设置:
yaml复制url: jdbc:mysql://localhost:3306/db?useSSL=false&serverTimezone=Asia/Shanghai
5.2 JPA懒加载异常
错误现象:
code复制could not initialize proxy - no Session
解决方法:
- 在Controller层使用
@Transactional - 或者使用DTO模式:
java复制@Query("SELECT new com.example.BearingDTO(p.skuCode, p.stock) FROM BearingProduct p")
List<BearingDTO> findAllBasicInfo();
5.3 日期格式处理
前端传参问题:
java复制@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date purchaseDate;
JSON序列化配置:
java复制@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
return builder -> builder
.serializers(new LocalDateSerializer(DateTimeFormatter.ISO_DATE))
.serializationInclusion(JsonInclude.Include.NON_NULL);
}
6. 功能扩展建议(加分项)
- 采购比价功能:
java复制public List<SupplierQuote> comparePrices(String skuCode) {
return supplierRepo.findAll().stream()
.map(supplier -> {
BigDecimal price = supplier.getQuotePrice(skuCode);
return new SupplierQuote(supplier.getName(), price);
})
.sorted(Comparator.comparing(SupplierQuote::getPrice))
.collect(Collectors.toList());
}
- 销售趋势分析:
sql复制SELECT
DATE_FORMAT(create_time,'%Y-%m') AS month,
SUM(total_amount) AS sales
FROM t_sales_order
GROUP BY month
ORDER BY month;
- 微信小程序端适配:
java复制@RestController
@RequestMapping("/api")
public class MobileController {
@GetMapping("/products")
public Result<List<ProductVO>> listProducts() {
return Result.success(productService.listAll());
}
}
在实现过程中,我发现轴承类产品的SKU编码规则特别重要。建议同学们在商品管理模块中加入自动校验功能,例如6205-2RS这种行业标准编码,可以通过正则表达式验证:
java复制private static final Pattern SKU_PATTERN =
Pattern.compile("^\\d{4}-[A-Z]{2}$");
public boolean isValidSku(String sku) {
return SKU_PATTERN.matcher(sku).matches();
}
