基于Spring Boot的商品库存扣减更新接口实现咨询
实现库存扣减的REST接口
一、PUT方法:通过请求体扣减指定商品库存
1. 修改Service接口(ProductoService.java)
新增库存扣减方法,拆分职责更清晰:
package com.coder.billing.services.Producto; import com.coder.billing.models.Producto; import java.util.List; public interface ProductoService { // 原有方法保留 List<Producto> getAllProductos(); Producto getOneProduct(Long id); Producto createProduct(Producto producto); Producto updateProduct(Producto producto, Long id); void deleteProduct(Long id); // 新增库存扣减方法 Producto deductStock(Long id, Integer cantidadProducto); }
2. 实现Service方法(ProductoServiceImpl.java)
实现扣减逻辑,同时校验库存充足性:
package com.coder.billing.services.Producto; import com.coder.billing.models.Producto; import com.coder.billing.repositories.Producto.ProductoRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service public class ProductoServiceImp implements ProductoService { @Autowired ProductoRepository productoRepository; // 原有方法保留 public List<Producto> getAllProductos() { return productoRepository.findAll(); } public Producto getOneProduct(Long id) { return productoRepository.findById(id).orElseThrow(() -> new RuntimeException("Producto no encontrado")); } public Producto createProduct(Producto producto) { return productoRepository.save(producto); } public Producto updateProduct(Producto producto, Long id) { Producto productoActual = productoRepository.findById(id).orElseThrow(() -> new RuntimeException("Producto no encontrado")); productoActual.setIdProducto(id); productoActual.setNombreProducto(producto.getNombreProducto()); productoActual.setPrecioProducto(producto.getPrecioProducto()); productoActual.setDescripcion(producto.getDescripcion()); productoActual.setStock(producto.getStock()); return productoRepository.save(productoActual); } public void deleteProduct(Long id) { productoRepository.deleteById(id); } // 实现库存扣减,添加事务保证原子性 @Transactional @Override public Producto deductStock(Long id, Integer cantidadProducto) { Producto producto = productoRepository.findById(id) .orElseThrow(() -> new RuntimeException("Producto no encontrado")); if (producto.getStock() < cantidadProducto) { throw new RuntimeException("库存不足,当前库存: " + producto.getStock()); } producto.setStock(producto.getStock() - cantidadProducto); return productoRepository.save(producto); } }
3. 修改Controller的PUT接口(ProductoController.java)
让PUT接口支持两种场景:全量更新商品信息,或仅扣减库存:
@PutMapping("/{id}") public ResponseEntity<ProductoDTO> updateProduct(@PathVariable Long id, @RequestBody ProductoDTO productoDTO) { Producto productoActual; // 若请求体包含有效扣减数量,执行库存扣减逻辑 if (productoDTO.getCantidadProducto() != null && productoDTO.getCantidadProducto() > 0) { productoActual = productoService.deductStock(id, productoDTO.getCantidadProducto()); } else { // 原有全量更新逻辑 Producto productoPeticion = modelMapper.map(productoDTO, Producto.class); productoActual = productoService.updateProduct(productoPeticion, id); } ProductoDTO productoDTORespuesta = modelMapper.map(productoActual, ProductoDTO.class); return ResponseEntity.ok(productoDTORespuesta); }
二、POST方法:传入商品数量实现库存扣减
如果需要独立的库存扣减接口(比如用于出库操作),可以新增POST接口:
1. (可选)创建专用DTO(StockDeductDTO.java)
用更精简的DTO传递参数:
package com.coder.billing.dto; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class StockDeductDTO { private Integer cantidadProducto; }
2. 在Controller中新增POST接口
@PostMapping("/{id}/deduct-stock") public ResponseEntity<ProductoDTO> deductStock(@PathVariable Long id, @RequestBody StockDeductDTO stockDeductDTO) { if (stockDeductDTO.getCantidadProducto() == null || stockDeductDTO.getCantidadProducto() <= 0) { throw new RuntimeException("请传入有效的扣减数量"); } Producto producto = productoService.deductStock(id, stockDeductDTO.getCantidadProducto()); ProductoDTO productoDTO = modelMapper.map(producto, ProductoDTO.class); return ResponseEntity.ok(productoDTO); }
若不想新增DTO,也可直接复用ProductoDTO:
@PostMapping("/{id}/deduct-stock") public ResponseEntity<ProductoDTO> deductStock(@PathVariable Long id, @RequestBody ProductoDTO productoDTO) { if (productoDTO.getCantidadProducto() == null || productoDTO.getCantidadProducto() <= 0) { throw new RuntimeException("请传入有效的扣减数量"); } Producto producto = productoService.deductStock(id, productoDTO.getCantidadProducto()); ProductoDTO productoDTORespuesta = modelMapper.map(producto, ProductoDTO.class); return ResponseEntity.ok(productoDTORespuesta); }
三、请求示例
PUT请求(更新商品+扣减库存)
PUT /api/productos/1 Content-Type: application/json { "nombreProducto": "更新后的商品名称", "cantidadProducto": 5 }
POST请求(仅扣减库存)
POST /api/productos/1/deduct-stock Content-Type: application/json { "cantidadProducto": 3 }
四、优化建议
- 异常处理:自定义异常类替代RuntimeException,搭配
@ExceptionHandler统一返回标准化错误响应(比如库存不足返回400,商品不存在返回404)。 - 并发控制:高并发场景下,可在库存扣减逻辑中添加乐观锁(比如在Producto实体添加
@Version字段),避免超卖。
内容的提问来源于stack exchange,提问作者Nacho
相关产品推荐
相关产品推荐

