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

Spring Boot Repository返回重复值问题排查求助

问题原因分析与解决方案

看起来你遇到的问题核心在于JPA实体映射的主键配置错误,导致JPA将数据库中不同的账户记录识别为同一个实体实例,最终返回重复的DTO数据。

为什么会出现重复记录?

JPA依靠实体的主键来区分不同的对象实例。如果你的AccountView实体把customer_number(客户编号)标记成了主键@Id,那所有属于同一个客户的账户都会被JPA判定为同一个实体——哪怕它们的账户编号(account_number)完全不同。这种情况下,JPA在查询时会把后续加载的同客户账户都替换成第一个加载的实例,最终返回的列表里全是重复的对象。

你可以先看一下控制台打印的account列表,如果打印出来的AccountView对象已经是重复的,那百分百是实体主键的问题。

解决方案

1. 修正AccountView的主键配置

每个账户应该有自己的唯一标识,也就是account_number,把它设置为主键才是正确的:

@Entity
@Table(name = "你的账户视图表名")
public class AccountView {
    @Id
    @Column(name = "account_number")
    private String accountNumber; // 账户编号作为唯一主键

    private String customerNumber; // 客户编号作为普通字段
    // 其他字段的映射...
    
    // Getter和Setter方法
}

2. 如果是复合主键的场景(比如视图没有单一唯一键)

如果你的AccountView是数据库视图,没有单一的唯一字段,可以用复合主键来标记,比如结合customer_number和account_number:
首先定义复合主键类:

@Embeddable
public class AccountViewPK implements Serializable {
    @Column(name = "customer_number")
    private String customerNumber;
    
    @Column(name = "account_number")
    private String accountNumber;

    // 必须实现无参构造、equals和hashCode方法
    public AccountViewPK() {}
    
    public AccountViewPK(String customerNumber, String accountNumber) {
        this.customerNumber = customerNumber;
        this.accountNumber = accountNumber;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        AccountViewPK that = (AccountViewPK) o;
        return Objects.equals(customerNumber, that.customerNumber) &&
               Objects.equals(accountNumber, that.accountNumber);
    }

    @Override
    public int hashCode() {
        return Objects.hash(customerNumber, accountNumber);
    }
}

然后在AccountView中使用复合主键:

@Entity
@Table(name = "你的账户视图表名")
public class AccountView {
    @EmbeddedId
    private AccountViewPK id;

    // 其他字段的映射...
    
    // Getter和Setter方法
}

同时更新Repository的泛型:

@Repository
public interface AccountRepository extends JpaRepository<AccountView, AccountViewPK> {
    List<AccountView> getByCustomerNumber(String cif);
    List<AccountView> getByCustomerNumberIn(List<String> cifList);
}

3. 验证Mapper转换逻辑(可选)

如果控制台打印的AccountView列表是正确的不同对象,但DTO重复,再检查AccountMapper的toAccountDto方法——不过从你贴的代码看,Mapper都是从account对象取字段值,没有硬编码或错误赋值的问题,所以这个概率很低。

按照上面的步骤修正后,JPA就能正确识别每个不同的账户记录,返回的DTO列表自然就会和数据库中的数据一致了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 19:42:39