ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

javaEE+SSH+MySQL百货供应链系统:从设计到部署全解析

javaEE+SSH+MySQL百货供应链系统:从设计到部署全解析 简介本资源是一套面向高校计算机专业本科生的毕业设计级供应链管理系统实战项目基于JavaEE平台采用SSHStruts2SpringHibernate经典三层架构结合MySQL实现百货中心采购、销售、库存、供应商协作等核心业务管理。资源适用于课程设计、毕设开发与Java Web技术巩固尤其适合需快速掌握企业级MVC开发流程的学习者。压缩包共179个文件涵盖50个核心Java业务类、26个JSP页面、19个XML配置文件、21个JS交互脚本及12个界面图标资源另含SQL建表语句、PPT设计文档与2个MP4辅导视频整体大小为117.58MB结构清晰、模块解耦明确。已有552人学习下载所有源码均经实测可一键部署运行配套文档详述系统分析、数据库设计与功能实现逻辑并提供完整操作流程说明与常见问题排错提示助力开发者高效复现与二次开发。 平时帮了不少同学和企业朋友梳理Java Web项目这次要聊的这套“基于javaEESSHmysql的百货中心供应链管理系统”放在今天看确实是有点年头的老技术组合了但恰恰是这种经典组合最适合用来理解Java Web开发从页面到数据库的完整链路。整个工程包含源码、数据库脚本和设计文档覆盖了从需求分析、数据库建模到业务功能落地的全过程。这篇文章我不想罗列功能清单而是把系统的设计逻辑、核心模块的实现方式、数据库表结构怎么设计、SSH三层框架如何整合以及我在实际部署和跑通项目过程中踩过的坑逐个拆开讲清楚。如果你正准备做类似的Java Web课程设计、毕业设计或者刚接触SSH框架想找个完整项目练手这篇文章可以直接当作操作手册来用。我会尽量用落实代码的方式讲不空谈概念每一个模块都给出关键表结构、核心配置和业务处理思路。1. 先把业务想明白百货中心供应链系统的核心逻辑1.1 传统供应链管理到底有哪些痛点百货中心的供应链管理本质上要解决的是“商品从供应商到门店再到顾客”这条链路上的信息同步问题。在没有系统化工具之前很多传统百货企业靠Excel表格、电话、纸质单据来传递采购、入库、销售、库存数据问题非常典型。第一是信息不同步。采购部下单给供应商货到了仓库仓库人手工入库但采购部可能还不知情财务部更不知道应付账款该记多少。这种信息孤岛导致账实不符、库存积压或者缺货断档。第二是手工操作容易出错。一张采购单涉及的字段很多——商品编码、供应商编号、单价、数量、税率、交货日期任何一个录入错误后面对账都是灾难。尤其是促销季商品数量大、流转快手工单据根本忙不过来。第三是库存难以实时掌控。百货中心的SKU数量动辄几千上万哪些商品快断货、哪些滞销积压、哪些即将过期靠人工盘点来掌握几乎是不可完成的任务。这直接影响采购决策——采购多了积压资金采购少了丢失销售机会。1.2 系统角色与功能边界基于上面的痛点这套供应链管理系统在功能设计上遵循了“按角色分权、按流程闭环”的原则。系统涉及的参与者主要有四类每一类角色的操作权限和关注点差异很大。系统管理员负责用户管理、基础数据维护、系统参数配置是整个系统的维护者。采购人员负责供应商管理、采购订单创建、采购入库确认关注的是商品和价格信息。仓库管理员负责库存查询、入库审核、出库登记、库存盘点关注的是数量和货位。销售/管理人员负责销售订单、销售退货以及查看销售报表、库存预警等分析数据关注的是经营结果。功能上系统围绕“采购—入库—库存—销售—出库”这条主线展开。商品管理、供应商管理、用户权限管理作为基础支撑模块再加上采购管理、销售管理、库存管理三个核心业务模块最后通过报表统计模块把整条链路的数据汇总出来。这个功能边界的划分很关键。很多初学做系统的时候容易犯一个毛病——功能越加越多最后做一个“四不像”。这套系统好就好在边界清晰每个模块解决的是供应链上的一段具体问题模块之间的数据流转关系明确采购单审核后生成入库单入库单更新库存表销售订单扣减库存库存不足时触发预警。2. 技术选型分析JavaEESSHMySQL这套组合的价值2.1 SSH三个框架各自负责什么SSH不是某一个框架而是Struts2、Spring、Hibernate三个框架的集成组合。很多初学者刚接触的时候搞不清楚这三个框架到底谁管谁代码里也是到处混着用。这里我用最直白的方式拆一下。Struts2负责的是Web层也就是浏览器发请求进来该由哪个Action处理、处理完跳转到哪个页面由Struts2的拦截器和配置文件来管理。它把Servlet开发中繁琐的请求参数封装、表单校验、页面跳转逻辑统一收口让Web层代码清爽很多。而且Struts2的拦截器机制很强大登录权限校验、字符编码处理都能做成拦截器统一链式执行。Spring在这一套里承担两个角色。首先是IoC容器负责管理对象的创建和依赖关系。Action、Service、DAO这些对象不再自己new出来而是统一交给Spring容器装配这样层与层之间的耦合度大大降低。比如采购Service需要调用库存DAOSpring通过依赖注入把DAO实例塞进来后续要换DAO实现类只要改配置不用改Java代码。其次是AOP事务管理这是Spring在供应链系统中价值最大的部分——一个完整的采购入库流程可能要同时操作采购单、入库单和库存表要么全成功要么全回滚。Spring声明式事务一个注解或者一段配置就能搞定比手动写Connection管理可靠太多。Hibernate负责的是持久层也就是Java对象和MySQL数据库表之间的映射转换。它的核心价值有两点一是消除了手写JDBC的重复代码PreparedStatement、ResultSet、异常处理这些样板代码全部由Hibernate代劳二是提供了面向对象的查询方式HQL和Criteria API可以直接操作对象而不是操作表。比如查询采购单关联的商品信息Hibernate会自动处理表关联按对象关系去取数据。2.2 为什么不换Spring BootSSH还有没有存在价值现在很多新项目已经用Spring Boot MyBatis Plus或者Spring Boot JPA那为什么还要回头学SSH这套老组合换个角度讲市面上还有大量存量系统跑在SSH架构上尤其是在零售、物流、制造这类信息化起步比较早的行业。一个百货中心如果真的运行了七八年的供应链系统底层大概率就是类似SSH这样的架构改造升级的前提是有人看得懂、改得动。从学习价值看SSH这套组合强制你理解配置、理解容器、理解ORM映射原理。比如Hibernate的SessionFactory怎么构建、一级二级缓存怎么管理、懒加载和N1问题怎么解决这些底层机制在Spring Boot里被自动配置掩盖了。很多直接用Spring Boot起步的开发者遇到“Failed to configure a DataSource”这类报错都不知道去哪找配置其实就是缺少对传统集成方式的理解。所以我的观点很明确如果你是为了快速上线一个全新的轻量应用那确实没必要用SSH但如果你是做课程设计、毕业设计或者要维护老系统SSH的工程化思想反而能让你理解得更深。这套系统选它从项目背景和历史环境来看是合理的。2.3 MySQL在这场戏里的角色MySQL在这套系统里是数据存储底座。供应链系统的核心是数据——商品资料、供应商档案、采购记录、库存快照、销售流水每一类数据都有明确的存储格式和关联关系。用MySQL搭配Hibernate有一个好处MySQL的InnoDB引擎支持事务和外键约束和数据一致性要求高的供应链业务天然匹配。Hibernate自动生成的SQL在MySQL上跑得很顺同时MySQL的性能调优手段也成熟索引优化、慢查询日志、连接池配置各类资料都很齐全。后面讲到数据库表设计的时候我会展开说明具体怎么建模。3. 架构分层与数据库设计整个系统的骨架3.1 经典三层架构怎么落地这套系统采用的是Java Web开发最经典的三层架构在代码层面分成Action层、Service层、DAO层再加上实体层和工具层。我见过不少项目虽然分了包但代码还是绕来绕去Action里直接写JDBC的都有。这里的关键是区分清楚每一层职责Action层是门面接收请求、封装参数、调用Service、返回页面或JSON结果。这一层不做业务逻辑只做流程转发。Service层是大脑业务规则在这里实现。比如采购入库时库存怎么更新、库存不足时销售订单怎么处理、怎么记录操作日志都是Service层该干的事。DAO层是手脚封装Hibernate操作只做增删改查不掺入业务判断。Entity层是模型对应数据库表结构定义属性和关联关系。各层之间通过接口和实现类解耦Service依赖DAO接口而不是具体实现这样测试和扩展都方便。以登录功能为例登录Action只负责接收用户名和密码调用UserService的login方法UserService调用UserDAO查询用户校验密码然后把结果返回给Action由Action决定跳转到主界面还是返回错误信息。3.2 核心数据表设计思路数据库设计是一个供应链系统最重要的部分。这套系统的核心表有九张左右我按业务模块分组说明。用户与权限相关的表有两张sys_user用户表字段包括user_id、username、password、real_name、role、status、create_time。其中role字段用字符串标识角色类型管理员、采购员、仓管员、销售员status控制账号是否启用。sys_role和sys_user_role如果要做更细粒度的权限可以拆出角色表和用户角色关联表支持一个用户多个角色、一个角色多个菜单权限。这套系统为了简洁直接用的单角色字段但在表结构上预留了扩展空间。商品与供应商基础资料相关的表有goods_info商品表字段包括goods_id、goods_code、goods_name、category_id、spec、unit、purchase_price、sale_price、stock_warn_num、status。purchase_price是采购价sale_price是销售价stock_warn_num是库存预警阈值低于这个数就自动告警。goods_category商品分类表字段是category_id、category_name、parent_id支持树形分类结构方便后续做多层类目管理。supplier_info供应商表字段包括supplier_id、supplier_code、supplier_name、contact_person、contact_phone、address、status。采购业务相关的表有两张采用主表明细表的经典设计purchase_order采购订单主表字段包括order_id、order_no、supplier_id、total_amount、order_status、create_by、create_time、audit_by、audit_time。order_status区分草稿、已审核、已入库、已作废四种状态。purchase_order_item采购订单明细表字段包括item_id、order_id、goods_id、purchase_price、quantity、subtotal。一张采购单对应多条明细这样在页面上可以一次录入多个商品。库存和销售业务相关的表也采用同样思路stock_info库存表字段包括stock_id、goods_id、quantity、warn_status、update_time。这个表可以理解成商品的实时库存快照入库加数量出库减数量。sale_order和sale_order_item销售订单主表和明细表字段设计模式跟采购订单完全对称。这里有一个很多人容易忽略的细节库存表里为什么不直接放goods_id和quantity就完事了还要单独做一张stock_info表因为商品基础信息是相对静态的数据而库存是高度动态的数据两者职责不同。如果把库存字段直接放到商品表里每次销售、退货、盘点都要更新商品表并发高的时候锁冲突会很严重。拆出来单独管理也方便后续做库存流水表。3.3 外键关系与索引设计表之间的关联关系很明确purchase_order通过supplier_id关联supplier_infopurchase_order_item通过order_id关联purchase_order通过goods_id关联goods_infostock_info通过goods_id关联goods_info。索引设计上除了主键索引建议在以下字段上单独建索引purchase_order表的order_no字段业务上经常按单号查询而且要求唯一建唯一索引。purchase_order_item表的order_id字段查明细的时候按主表ID过滤建普通索引。purchase_order表、sale_order表的create_time字段做报表统计时经常按时间范围查询建普通索引。goods_info表的goods_code字段商品编码在业务中作为唯一检索条件建唯一索引。Hibernate配置外键关联时还要注意一对多场景下的懒加载策略配置。默认情况下查询采购订单主表时关联的明细列表是懒加载的只有真正访问getItems()时才发SQL查数据库。这意味着在Service层事务范围内访问明细数据永远没问题但如果在Action层、事务已经提交之后再访问就会抛出LazyInitializationException。这个坑下面排错部分我会详细讲怎么处理。4. 核心模块实现与关键代码每个模块到底怎么落地4.1 登录与权限控制实现登录模块看起来简单但它是系统安全的第一道门槛。实现上用的是Struts2拦截器加Spring管理Service。先定义一个LoginInterceptor拦截器在struts.xml里配置拦截器栈除了登录Action和几个基础页面之外其它所有请求都要经过这个拦截器判断session中是否存在user对象。关键代码如下public class LoginInterceptor extends AbstractInterceptor { Override public String intercept(ActionInvocation invocation) throws Exception { MapString, Object session invocation.getInvocationContext().getSession(); SysUser user (SysUser) session.get(loginUser); if (user null) { // 未登录跳转到登录页面 return login; } return invocation.invoke(); } }struts.xml中配置拦截器栈package namedefault namespace/ extendsstruts-default interceptors interceptor nameloginInterceptor classcom.depart.ssh.interceptor.LoginInterceptor/ interceptor-stack nameauthStack interceptor-ref namedefaultStack/ interceptor-ref nameloginInterceptor/ /interceptor-stack /interceptors action nameuser_* classcom.depart.ssh.action.UserAction method{1} interceptor-ref nameauthStack/ result namesuccess/pages/main.jsp/result result namelogin/login.jsp/result /action /package密码存储方面系统使用MD5加密后存储而不是明文。虽然MD5现在已经不是最安全的加密方式但对于课程设计和内部系统已经能说明基本的加密意识。如果是实际生产环境建议升级为BCrypt或者加盐MD5。权限控制方面除了登录判断系统还做了基于角色的菜单和按钮控制。管理员登录后可以看到用户管理菜单普通用户看不到采购员只有采购相关按钮的权限。实现方式是在JSP页面通过自定义标签或者JSTL判断当前用户的role字段控制按钮是否显示。4.2 采购入库流程一个完整的事务案例采购入库是供应链系统里最典型的多表事务操作非常适合用来说明Spring事务管理的价值。流程是这样的采购员创建采购订单选择供应商和商品录入采购数量和采购价订单先保存为“草稿”状态审核通过后才能入库。仓库管理员操作入库时系统要做三件关联的事更新采购订单状态从“已审核”改成“已入库”。生成或更新库存记录如果商品已经存在于库存表直接累加数量如果是首次入库插入一条新的stock_info记录。记录库存流水向stock_log表插入一条入库记录包含商品、数量、操作类型、操作人、时间。这三件事任何一个失败整个入库操作都应该回滚。如果不用Spring事务你可能要在Service层手动用try-catch管理Connection的commit和rollback代码会变得很臃肿。而用Spring的Transactional注解只需要在PurchaseService的stockIn方法上加一行Service Transactional(rollbackFor Exception.class) public class PurchaseServiceImpl implements PurchaseService { Autowired private PurchaseOrderDao purchaseOrderDao; Autowired private StockDao stockDao; Autowired private StockLogDao stockLogDao; Override public void stockIn(Integer orderId, SysUser operator) { PurchaseOrder order purchaseOrderDao.getById(orderId); if (order null || !2.equals(order.getOrderStatus())) { throw new BusinessException(订单不存在或状态不允许入库); } // 1. 更新订单状态 order.setOrderStatus(3); purchaseOrderDao.update(order); // 2. 遍历明细更新库存 ListPurchaseOrderItem items order.getItems(); for (PurchaseOrderItem item : items) { StockInfo stock stockDao.getByGoodsId(item.getGoodsId()); if (stock null) { stock new StockInfo(); stock.setGoodsId(item.getGoodsId()); stock.setQuantity(item.getQuantity()); stockDao.save(stock); } else { stock.setQuantity(stock.getQuantity() item.getQuantity()); stockDao.update(stock); } // 3. 记录库存流水 StockLog log new StockLog(); log.setGoodsId(item.getGoodsId()); log.setChangeType(in); log.setQuantity(item.getQuantity()); log.setOperator(operator.getRealName()); log.setCreateTime(new Date()); stockLogDao.save(log); } } }在写这套流程的时候我心里很清楚一个前提这里的Hibernate操作必须使用Spring管理的事务DAO层不能再开自己的Session。这些配置会统一放在applicationContext.xml里把SessionFactory交给Spring管理Service实现类声明式事务生效DAO通过HibernateTemplate或者直接注入SessionFactory操作。4.3 销售出库与库存扣减销售模块的业务逻辑和采购入库正好相反。创建销售订单时系统要检查每个商品的库存是否足够如果当前库存小于销售数量直接给出提示不允许创建订单。这个“检查库存”的逻辑看似简单但在多线程高并发场景下存在一个经典的超卖问题。假设库存只剩1件两个用户同时下单都查到库存1都通过了校验各自扣减库存最后库存变成了-1。解决的办法有两种第一种是数据库层面解决在stock_info表加乐观锁版本号版本字段。更新库存时带上版本号条件String hql update StockInfo set quantity quantity - ? , version version 1 where goodsId ? and version ? and quantity ?;如果影响行数为0说明库存已经被别人改过重新查询再校验。第二种是用数据库行锁在查询时加for update把当前行锁住其它事务只能等待。Hibernate里可以通过session.createQuery(from StockInfo where goodsId :goodsId) .setParameter(goodsId, goodsId) .setLockMode(stock, LockMode.PESSIMISTIC_WRITE) .uniqueResult();对于百货中心这类并发量没有那么极端的业务场景用乐观锁就足够了性能和实现的复杂度都比较可控。排错的时候如果发现库存数据不对优先检查是不是这里出了问题。4.4 Hibernate关联映射与查询优化Hibernate的对象关系映射是SSH开发中容易写乱的地方。采购订单主表和明细表的映射配置在实体类上体现为Entity Table(name purchase_order) public class PurchaseOrder { private Integer orderId; private String orderNo; private SupplierInfo supplier; private ListPurchaseOrderItem items; Id GeneratedValue(strategy GenerationType.IDENTITY) Column(name order_id) public Integer getOrderId() { return orderId; } ManyToOne(fetch FetchType.LAZY) JoinColumn(name supplier_id) public SupplierInfo getSupplier() { return supplier; } OneToMany(mappedBy order, fetch FetchType.LAZY, cascade CascadeType.ALL) public ListPurchaseOrderItem getItems() { return items; } }映射关系有几个关键配置点。FetchType.LAZY代表懒加载查询订单列表时不加载供应商和明细只有用到的时候才触发查询。CascadeType.ALL表示保存订单时级联保存明细这样在Service层只需要save(order)所有子表记录会自动插入不需要手动逐条保存明细。查询优化方面SSH项目最常见的性能问题就是N1。比如查询采购订单列表时先查出所有订单然后遍历每个订单去查询供应商信息产生N条额外SQL。解决思路是如果用HQL用fetch关键字把关联对象一次性查出来String hql from PurchaseOrder o left join fetch o.supplier left join fetch o.items;用fetch后Hibernate会生成关联查询SQL一次性把关联数据查出来避免循环查询。5. 工程目录与部署拿到压缩包后怎么跑起来5.1 压缩包里的完整工程结构拿到“JAVAEE-SSH供应链管理系统.zip”压缩包之后解压出来会看到一套标准的Maven或传统Web项目目录。Maven版的目录结构大致是src/main/java com.depart.ssh action/ // Struts2的Action类 service/ // Service接口和实现类 dao/ // DAO接口和实现类 entity/ // Hibernate实体类 util/ // 工具类 interceptor/ // 拦截器 src/main/resources struts.xml applicationContext.xml spring-mvc.xml如果有 hibernate.cfg.xml 或 Spring里配置的SessionFactory jdbc.properties src/main/webapp WEB-INF/web.xml pages/ // JSP页面 css/js/images/ // 静态资源 database init.sql // 建库建表脚本 data.sql // 初始数据脚本 doc/ 需求文档.docx 设计文档.docx 答辩PPT.pptx README.md拿到工程第一件事不是急着改代码而是先看README和database目录下的SQL脚本。用Navicat或者MySQL命令行执行init.sql和data.sql把数据库建好。5.2 配置文件修改与启动步骤数据库连接配置在jdbc.properties里核心就四项jdbc.driverClasscom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/depart_supply?useUnicodetruecharacterEncodingutf8 jdbc.usernameroot jdbc.password123456URL里的characterEncodingutf8一定要加上否则mysql插入中文的时候会变成乱码。MySQL 8.x版本还要注意驱动类名换成com.mysql.cj.jdbc.Driver并且URL里加上serverTimezoneAsia/Shanghai否则会报时区异常。启动步骤按下面顺序来启动MySQL导入database目录下的SQL脚本确认四张核心表已经建好。在IDEA里导入项目如果是Maven项目等依赖下载完成。SSH框架依赖的关键版本不要随便动Struts2、Spring、Hibernate三者有版本兼容性要求。例如Struts2 2.3.x配Spring 4.x是常见的组合升级其中一个版本可能导致别的问题。修改jdbc.properties的数据库用户名和密码。配置Tomcat选择本地安装的Tomcat 7/8/9版本。需要注意的是如果用的是JDK 8以上版本某些老版本Tomcat可能不兼容建议直接装Tomcat 8.5。启动Tomcat访问http://localhost:8080/系统上下文路径/看到登录页面就说明部署成功。5.3 初始账号与功能演示路径数据库初始化脚本里通常会预置几个测试账号。比如admin/123456是管理员purchase/123456是采购员stock/123456是仓管员。第一次登录建议用管理员账号先到用户管理里把账号密码改掉再按业务链路走一遍先在供应商管理添加供应商在商品管理添加商品和库存预警阈值然后创建采购订单审核入库最后创建销售订单验证库存扣减和预警功能。这样一条链路走完系统的基本功能就全部验证过了。6. 常见问题与排查技巧我踩过的坑都在这6.1 数据库连接和环境配置类问题问题一Hibernate启动时报错提示找不到数据源或者连接数据库失败。最常见的两种原因一是MySQL服务没启动Windows服务管理器里检查一下MySQL服务状态二是jdbc.properties里配置的账号密码不对或者URL里的数据库名写错了。还有一种隐蔽情况是MySQL 8的加密规则和老驱动不兼容报错里看到caching_sha2_password相关字样那就把驱动换成最新的mysql-connector-java 8.x版本。问题二页面中文乱码。这个问题的排查要从三层入手。第一层是数据库表字符集建表时用utf8mb4第二层是JDBC连接字符串加了characterEncodingutf8第三层是JSP页面编码和Struts2拦截器的编码设置。Struts2默认编码是UTF-8可以在struts.xml里显式配一下同时确保JSP页面头部有pageEncodingUTF-8。问题三Tomcat启动时端口被占用。执行netstat -ano | findstr 8080找到占用8080端口的进程PID然后任务管理器结束进程或者直接改Tomcat的server.xml端口。6.2 SSH框架集成类问题问题一ClassNotFoundException。这类报错十有八九是包没引全或者版本冲突。SSH三个框架依赖的第三方库非常多尤其要注意commons-xxx系列、javassist、log4j这些公共库的版本一致性。用Maven管理依赖的话检查pom.xml里有没有版本号冲突如果用的是传统lib目录导入检查jar包是不是重复了。问题二LazyInitializationException懒加载异常。前面提过在Action层访问懒加载对象时会报这个错。我当时最常用的解决方案是在web.xml配置OpenSessionInViewFilter让Hibernate的Session在整个请求周期内保持打开状态filter filter-nameopenSessionInViewFilter/filter-name filter-classorg.springframework.orm.hibernate4.support.OpenSessionInViewFilter/filter-class /filter filter-mapping filter-nameopenSessionInViewFilter/filter-name url-pattern/*/url-pattern /filter-mapping但要注意这个方案只是“掩盖”了问题Session关闭时机被延后到了视图渲染结束。如果数据量特别大长事务会带来连接池耗尽风险。更推荐的做法是在Service层就把需要展示的数据准备好通过VO传给Action避免在视图层懒加载。问题三Action接收不到参数或者表单提交后中文乱码。Struts2环境下确认两件事第一表单的method是post第二struts.xml里有没有配编码拦截器或者web.xml里有没有配CharacterEncodingFilter。Struts2的默认编码是UTF-8如果表单页面本身是GBK编码两边就不一致了。6.3 Hibernate与MySQL联动类问题问题一Hibernate生成的表名或字段名和MySQL关键字冲突。比如常见的user表或者字段叫order、desc、status在MySQL里可能是保留字。解决办法有三种一是建表时用反引号括起来二是在Hibernate实体类注解里用Table(name sys_user)显式指定表名避免用关键字三是改字段名比如order改成order_no或purchase_order。这个坑几乎每个SSH项目都会遇到早改早省事。问题二数据量大后查询变慢。排查SQL执行效率最直接的方法是打开Hibernate的SQL日志在log4j或者logback配置里把org.hibernate.SQL级别设为DEBUG。看控制台输出的SQL用EXPLAIN看有没有走索引。通常供应链系统的慢查询集中在采购订单和销售订单表因为数据量增长快下单时又会带多个条件查询。在order_no和create_time上建好索引性能能改善很多。问题三库存数据在并发操作下出现负数或者漏扣。这个在前面已经讲过了核心是用乐观锁或悲观锁保证扣减库存的原子性。另外注意库存操作一定要放在事务里如果事务传播配置不对比如写成了REQUIRES_NEW就会出现一个事务提交了另一个还没提交读到脏数据的情况。6.4 部署运行阶段的高频问题部署到Tomcat时最常遇到的是JDK版本和Tomcat版本不匹配。SSH老项目如果用JDK 9以上的版本编译可能出现模块访问限制错误此时建议换回JDK 8并且把Tomcat也换成配套版本。另一个问题是context路径配置错误部署后访问404。检查一下war包名称和访问URL是否一致。还有一点务必留意如果服务器本身是Linux环境MySQL的安装配置教程里提到过grant授权命令配置完以后要flush privileges。百货物料的供应链系统如果部署在Linux服务器上其实和生产环境更贴近建议在VMware虚拟机里装一个Linux把项目完整部署一遍。踩坑后的几点心得这套系统我前后完整跑通过三次最有价值的一句话总结是SSH不是难在写代码而是难在理解框架之间怎么配合。Struts2管请求、Spring管对象和事务、Hibernate管数据库映射你在写一个模块的时候脑子里要时刻清楚当前这行代码属于哪一层这一层该不该做这件事。给学生朋友的建议是拿到工程后先不要急着跑起来先花一晚上把数据库脚本从头到尾读一遍把表关系画出来。然后在源码里搜索HQL语句看每个模块的数据是怎么流转的。最后再动手改功能——比如给采购订单加一个审批人字段或者给库存表加一个货位号。这样改一遍你对这套系统的理解比单纯跑通要深得多。最后再分享一个小技巧如果编译打包时老是报依赖缺失或者版本冲突强烈建议用Maven的dependency:tree命令看看完整的依赖树排查冲突的jar包。我在实际项目里遇到过commons-logging被多个框架以不同版本引入导致运行时不停报NoSuchMethodError最后就是用这个命令定位到冲突源头在pom.xml里加了exclusions排除掉旧版本解决了。这类框架整合问题排错工具用对了往往几分钟就能搞定。本文还有配套的精品资源点击获取
返回列表