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

Spring Boot调用SQL Server存储过程时API返回重复列表记录

异常根因

这个问题和SQL Server端的存储过程逻辑完全无关,核心问题出在Spring Data JPA的结果映射规则上:
你在GioHang实体上把id_khach_hang字段标注成了@Id,但实际存储过程的返回结果里,同一个id_khach_hang对应多条不同的购物车条目(差异在id_xe、so_luong字段)。
JPA处理原生查询结果集映射时,会以实体标注的主键值为唯一标识做对象复用——只要某一行的主键值和之前已经映射过的记录一致,就会直接返回第一次构造的实体实例,不会为这一行生成新的对象。最终你拿到的列表里所有元素,其实都是第一次映射出来的那个对象的引用,自然所有内容都和第一条完全一样。

可落地的解决方法

方法1:修正实体的复合主键定义

你的结果集不存在单列唯一主键,实际的唯一标识是id_khach_hang + id_xe的组合,按照JPA的复合主键规则调整实体结构即可:

  • 新建实现了序列化接口的复合主键类GioHangId,包含id_khach_hang、id_xe两个属性,重写equals和hashCode方法
  • 修改原GioHang实体:移除单独标注在id_khach_hang上的@Id,在类上添加@IdClass(GioHangId.class),同时在id_khach_hang、id_xe两个字段上分别标注@Id
  • 调整完成后,JPA会基于两个字段的组合判断记录唯一性,即可正确映射存储过程返回的所有行。

方法2:用非实体DTO承接查询结果

如果不想改动现有实体的结构,可以完全绕开JPA的实体映射和主键去重逻辑:

  • 新建普通POJO类GioHangDTO,属性和存储过程返回的字段一一对应(id_khach_hang、id_xe、so_luong),补上对应的getter、setter方法,不需要加@Entity注解
  • 修改仓储层的查询方法返回值,从List<GioHang>替换为List<GioHangDTO>
  • 确保存储过程返回的列名和DTO的字段名完全匹配,调用时即可拿到所有无重复的正确记录。

注意:这类没有单列唯一主键的存储过程查询,不建议直接使用JPA实体做返回类型,否则必然触发主键判断带来的记录覆盖、返回重复的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.28 01:15:02