Spring Boot药品应用卖出药品后表行除med_id外字段值丢失求助
药品库存扣减导致字段清空的问题定位与修复方案
核心问题根因排查
结合你描述的“除med_id外所有字段被清空”的现象,对应几个高频触发原因:
- 误用Spring Data JPA的全量更新逻辑:JPA的
save()方法在传入实体带主键时,会将实体对象的所有字段值同步覆盖到数据库行——如果传入的实体是手动new出来的,仅设置了med_id和待修改的库存字段,其余字段全部为null,就会直接把数据库里的其他列清空为null,完全匹配你遇到的现象。 - 业务层操作逻辑缺失实体加载步骤:处理卖出请求时,没有先根据med_id从数据库查询出完整的药品信息实体,而是直接实例化新的MedCRUD对象做参数赋值,后续更新自然会带着空值覆盖原有数据。
- 前端表单参数传递不全:卖出页的表单没有将药品原有名称、单价等非用户输入项的值完整传递到后端,导致后端绑定的MedCRUD实体对应字段为null,最终被更新到数据库。
- 实体类字段映射配置错误:比如med_quantity、med_quantitys等字段的
@Column注解和数据库列名不匹配,导致JPA更新时无法正确读取原有字段值,写入空值。
可直接落地的修复步骤
1. 重构业务层卖出操作流程
完全按照JPA的正确使用逻辑调整操作顺序,避免全量空值覆盖:
- 接收前端传参后,先通过
Medicine_Repository.findById(med_id)查询出数据库内存储的完整药品实体,禁止直接new MedCRUD对象做更新操作 - 做库存前置校验:判断查出实体的
med_quantity是否大于等于用户输入的购买数量,库存不足时直接返回对应提示,中断后续操作 - 在查出的完整实体上直接修改对应字段值:
- 扣减剩余库存:
实体.setMed_quantity(实体.getMed_quantity() - 购买数量) - 累加累计售出量:
实体.setMed_quantitys(实体.getMed_quantitys() + 购买数量) - 累加售出总价:
实体.setSellTotalPrice(实体.getSellTotalPrice() + 购买数量 * 实体.getMedPrice())
- 扣减剩余库存:
- 将修改后的完整实体传入
save()方法执行更新,此时实体所有字段都有从数据库查出的原值,不会出现空值覆盖的问题
2. 优化卖出页前端表单逻辑
- 所有不需要用户编辑的药品原有属性(药品名称、单价等),在表单内用
<input type="hidden">隐藏域存储值,确保提交时这些参数能完整传递到后端 - 药品列表的卖出操作入口,需携带对应药品的med_id参数,卖出页加载时根据med_id查询完整药品信息填充表单,避免参数缺失
3. 可选优化:使用局部更新逻辑规避全量覆盖风险
可以在持久层直接自定义更新语句,完全绕过实体全量更新的逻辑,从数据库层面做精准字段修改,比如:
@Modifying @Transactional @Query("update MedCRUD m set m.med_quantity = m.med_quantity - :buyNum, m.med_quantitys = m.med_quantitys + :buyNum, m.sellTotalPrice = m.sellTotalPrice + :buyNum * m.medPrice where m.medId = :medId and m.med_quantity >= :buyNum") int deductStock(@Param("medId") Integer medId, @Param("buyNum") Integer buyNum);
这种写法规避实体缺字段导致的覆盖问题,执行效率更高,也能在SQL层面做库存校验,防止超卖。
关键提醒:Spring Data JPA的
save()方法是典型的upsert实现——当传入实体带主键时,会更新实体映射的所有列,哪怕列值为null也会写入数据库,不要误以为它只会更新有值的字段。
内容的提问来源于stack exchange,提问作者shivendra yadav
相关产品推荐
相关产品推荐

