JPA查询报错:多匹配标识符行问题排查与解决
问题分析与修复方案
问题根源
出现More than one row with the given identifier was found错误的核心原因是实体类关联关系与数据库结构不匹配:
- 数据库中
account和card是一对多关系(一个账户可对应多张卡片),但你在实体类中错误使用了@OneToOne注解定义关联 - Hibernate会将
@OneToOne关联的外键(account_id)视为唯一约束,认为一个账户只能对应一张卡片 - 测试数据中同一账户
00000000-0000-0000-0000-000000000ac1下存在多张卡片,当排除ACTIVE状态外的其他状态时,仍有多个匹配记录,触发Hibernate的唯一检查抛出异常;仅ACTIVE状态正常是因为该状态下该账户只有一张卡片,刚好符合@OneToOne的唯一约束
修复步骤
1. 修正实体类关联关系
将@OneToOne改为符合数据库结构的@ManyToOne和@OneToMany:
修改Card类:
package by.afinny.credit.entity; import by.afinny.credit.enumeration.CardStatus; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; import java.util.UUID; @Entity @Table(name = "card") @Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder public class Card { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private UUID id; @Enumerated(EnumType.STRING) @Column(name = "status", nullable = false, length = 30) private CardStatus cardStatus; // 替换@OneToOne为@ManyToOne,匹配一对多关系 @ManyToOne(cascade = CascadeType.MERGE) @JoinColumn(name = "account_id", referencedColumnName = "id") private Account account; }
修改Account类:
package by.afinny.credit.entity; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; import java.util.List; import java.util.UUID; @Entity @Table(name = "account") @Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder public class Account { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private UUID id; // 替换@OneToOne为@OneToMany,关联Card集合 @OneToMany(mappedBy = "account") private List<Card> cards; }
2. 验证Repository与测试逻辑
CardRepository中的findByAccountIdAndCardStatusNot方法无需修改,Spring Data JPA会自动适配一对多关系的查询- 修改后测试方法会正确返回该账户下排除指定状态的所有卡片,
verifyProperties方法的断言逻辑可正常执行
补充说明
数据库中card表的account_id未设置唯一约束,本身就是一对多关系的体现,实体类的关联注解必须与数据库结构完全匹配,否则Hibernate会基于错误的关联规则执行数据加载,导致异常。
内容的提问来源于stack exchange,提问作者Sergey Zolotarev
相关产品推荐
相关产品推荐

