You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot接口报400错误:无法反序列化java.lang.Long类型值

解决POST接口/shop/order的400错误及库存扣减逻辑问题

一、400 Bad Request错误的根因与修复

控制台抛出的JSON parse error: Cannot deserialize value of type java.lang.Long from Object value明确指向:请求的JSON格式不匹配Controller接收的Map<String, Long>类型,某个值是对象结构而非预期的Long数值。

修复步骤:

  1. 修正请求体格式
    确保Postman发送的JSON是componentId为键、购买数量(Long类型)为值的结构,示例:

    {
      "COMP-001": 2,
      "COMP-002": 1
    }
    

    禁止发送类似{"COMP-001": {"count": 2}}这种值为嵌套对象的格式。

  2. 检查请求头配置
    确认Postman的Content-Type请求头设置为application/json,否则Spring无法正确解析JSON请求体。

二、Service层逻辑错误修复

当前Service代码存在两个致命问题:

  • 把List<PartDetails>强制转换为单个PartDetails对象,会直接抛出ClassCastException;
  • 注释掉了零件不存在的异常处理,若传入无效componentId,后续代码会触发空指针或类型转换错误。

修复后的Service代码:

@Transactional
public void placeOrder(Map<String, Long> orderDetails) {
    for (Map.Entry<String, Long> entry : orderDetails.entrySet()) {
        String componentId = entry.getKey();
        Long requestedUnits = entry.getValue();
        
        // 获取对应零件详情,不存在则抛出异常
        PartDetails partStock = partRepository.findByComponentId(componentId)
                .stream()
                .findFirst()
                .orElseThrow(() -> new RuntimeException("Part stock not found with component ID: " + componentId));
        
        Long currentUnits = partStock.getUnitInStock();
        if (currentUnits < requestedUnits) {
            throw new RuntimeException("Insufficient units in stock for component ID: " + componentId);
        }
        partStock.setUnitInStock(currentUnits - requestedUnits);
        partRepository.save(partStock);
    }
}

三、Repository层优化

  1. 修正主键泛型类型
    PartDetails的主键id是Long类型,但当前Repository泛型写的是CrudRepository<PartDetails, String>,会导致主键操作时类型不匹配。修正为:

    public interface PartRepository extends CrudRepository<PartDetails, Long> {
        // 保留原有查询方法
        @Query("SELECT p FROM PartDetails p WHERE p.carModelId = :carModelId")
        List<PartDetails> findByCarModelId(String carModelId);
    
        @Query("SELECT p FROM PartDetails p WHERE p.componentId = :componentId")
        List<PartDetails> findByComponentId(String componentId);
    }
    
  2. 优化查询方法语义
    如果componentId是唯一字段(每个ID对应一个零件),建议将findByComponentId改为返回Optional<PartDetails>,更符合业务逻辑:

    @Query("SELECT p FROM PartDetails p WHERE p.componentId = :componentId")
    Optional<PartDetails> findByComponentId(String componentId);
    

    此时Service层可简化为:

    PartDetails partStock = partRepository.findByComponentId(componentId)
            .orElseThrow(() -> new RuntimeException("Part stock not found with component ID: " + componentId));
    

四、额外优化建议

  • 精细化异常处理:Controller当前捕获所有Exception返回500,建议区分异常类型返回对应状态码,比如零件不存在返回404、库存不足返回400,前端能更精准处理错误;
  • 使用DTO封装请求:创建OrderRequest类代替Map<String, Long>,提升代码可读性和可维护性,示例:
    public class OrderRequest {
        private Map<String, Long> components;
        // 生成getter、setter
    }
    
    然后Controller参数改为@RequestBody OrderRequest orderRequest。

内容的提问来源于stack exchange,提问作者Vishesh Dab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 13:07:39