Spring Boot使用PutMapping更新Product如何仅传需修改字段
问题分析
当前代码的核心问题:
- 直接将传入的
Product对象保存到数据库,未传入的字段会被设为null(或默认值),导致数据库字段被错误覆盖,进而触发500错误。 - 通过
findAll()遍历所有产品查找目标数据,效率极低,数据量增大后问题会更明显。 - 控制器中的
upc参数未被实际使用,属于冗余参数。
解决方案
1. 优化Repository查询方法
先在ProductRepository中添加根据upc查询单个产品的方法,替代全表查询:
public interface ProductRepository extends JpaRepository<Product, String> { Optional<Product> findByUpc(String upc); }
2. 修改服务层的updateProduct方法
改为先查询数据库中的原实体,再将传入的非空字段增量更新到原实体,最后保存原实体:
@Override public Status updateProduct(Product product) { // 根据upc查询数据库中的目标产品 Optional<Product> optionalProduct = productRepository.findByUpc(product.getUpc()); if (optionalProduct.isPresent()) { Product existingProduct = optionalProduct.get(); // 仅更新传入的非空字段 if (product.getProductName() != null) { existingProduct.setProductName(product.getProductName()); } if (product.getBrand() != null) { existingProduct.setBrand(product.getBrand()); } if (product.getCategory() != null) { existingProduct.setCategory(product.getCategory()); } if (product.getPrice() != null) { existingProduct.setPrice(product.getPrice()); } // 若有description字段(示例中提到但表结构未定义,自行调整) // if (product.getDescription() != null) { // existingProduct.setDescription(product.getDescription()); // } productRepository.save(existingProduct); return Status.SUCCESS; } return Status.PRODUCT_NOT_FOUND; }
3. 调整控制器代码
去掉冗余的upc参数,直接从请求体的Product对象中获取upc,同时修正状态码的合理性:
@PutMapping("/updateproduct") public ResponseEntity<String> updateProduct(@RequestBody Product product) { Status stt = productService.updateProduct(product); if (stt == Status.SUCCESS) { return ResponseEntity.status(HttpStatus.OK).body("Product Updated Successfully!"); } else if (stt == Status.PRODUCT_NOT_FOUND) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Product with upc = " + product.getUpc() + " Not Found!"); } else { return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null); } }
注:将产品不存在的响应码从
BAD_REQUEST改为符合REST规范的NOT_FOUND(404)。
4. 确保实体类字段映射正确
如果数据库字段是下划线命名(如product_name),实体类是驼峰命名(productName),需保证映射正确,可通过注解或开启驼峰自动映射:
@Entity @Table(name = "product") public class Product { @Id @Column(name = "upc") private String upc; @Column(name = "product_name") private String productName; @Column(name = "brand") private String brand; @Column(name = "category") private String category; @Column(name = "price") private BigDecimal price; // 省略getter、setter、构造方法 }
测试验证
现在可以仅传入upc和需要修改的字段,示例请求如下:
{ "upc": "100101101111", "productName" : "Dove" }
此时只会更新productName字段,其他字段保持数据库原有值,不会触发500错误。
内容的提问来源于stack exchange,提问作者Kim Gordon
相关产品推荐
相关产品推荐

