Hibernate存在关联数据错误时如何正常返回查询结果
问题根因
这个报错是Hibernate默认的关联完整性校验逻辑导致的:配置@ManyToOne关联后,Hibernate默认认定关联字段存储的外键值一定能在关联表匹配到对应主键,一旦碰到外键值在关联表无对应记录的脏数据(比如你这里Student表中Jack对应的school值NY),即使配置了懒加载,在结果集遍历、关联代理初始化时就会抛出No row with the given identifier exists异常。外键值为null的记录(比如Samuel那条)不会触发这个报错。
解决方案
根据你的需求,选以下任意一种方案即可:
- 方案1:加注解忽略关联缺失错误
在Student实体的school关联字段上添加Hibernate内置的@NotFound注解,配置遇到缺失关联时直接赋值为null、不抛出异常,代码修改如下:
加完注解后执行全表查询不会报错,所有Student记录都会返回,其中Jack的school属性会被自动映射为null。如果你需要直接过滤掉这类关联无效的脏记录,只需要在业务代码里额外判断:当student对象的school为null、且数据库中对应school字段非空时直接跳过即可。import org.hibernate.annotations.NotFound; import org.hibernate.annotations.NotFoundAction; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "school") @NotFound(action = NotFoundAction.IGNORE) private School school; - 方案2:自定义JPQL查询直接过滤无效记录
不依赖默认的实体加载逻辑,手写JPQL通过左连接直接在数据库层面过滤掉脏数据,查询语句示例:
这个查询返回的结果直接就是你需要的4条有效记录(Albert、Kevin、Robert、Samuel),不会触发关联校验报错,也不需要修改实体注解。select s from Student s left join s.school sch where sch is not null or s.school is null - 方案3:清理脏数据(长期最优方案)
从数据根源解决问题:要么在School表补充id为NY的对应学校记录,要么把Student表中Jack对应的school字段更新为合法值或者null,符合数据库外键完整性约束,从根源避免这类报错。
内容的提问来源于stack exchange,提问作者G. Ciardini
相关产品推荐
相关产品推荐

