Spring Boot多对一关联出现EntityNotFoundException但数据实际存在
解决Spring Boot多对一关联下的EntityNotFoundException(数据库数据存在但仍抛出异常)
我之前也踩过这个一模一样的坑——明明数据库里关联的实体数据好好躺着,JPA却硬抛出javax.persistence.EntityNotFoundException,结合你给出的Beneficiaire实体代码,咱们来逐一排查可能的原因和对应的解决办法:
一、关联字段的类型或配置不匹配
这是最常见的原因,一定要仔细核对:
- 主键与外键的类型不一致:比如关联你的
Beneficiaire的实体里,外键字段的Java类型是Long,但Beneficiaire的主键idBenef是Integer,或者数据库里外键列是bigint而主键列是int,这种类型不匹配会导致JPA查询时匹配不到数据。 - @JoinColumn配置错误:如果关联实体里的
@JoinColumn参数写错了也会出问题,比如:name属性和数据库实际的外键列名不对应;- 如果关联的不是主键而是唯一键(比如你
Beneficiaire里的noBenef),没有指定referencedColumnName = "noBenef",JPA会默认去找主键idBenef,自然找不到数据。
举个正确配置关联唯一键的例子:
@ManyToOne @JoinColumn(name = "benef_no", referencedColumnName = "noBenef") private Beneficiaire beneficiaire;
二、懒加载导致的会话失效问题
多对一关联默认是懒加载(FetchType.LAZY),如果你在事务范围外访问关联实体的属性,此时JPA的会话已经关闭,就会触发加载失败,有时候也会表现为EntityNotFoundException。
解决办法:
- 确保你访问关联属性的代码处在事务范围内(比如加
@Transactional注解); - 可以临时改为急加载(
@ManyToOne(fetch = FetchType.EAGER))测试是否是懒加载的问题,但注意急加载可能带来性能损耗,不建议长期用。
三、数据库数据的隐性不一致
别光看表面数据存在,要检查细节:
- 关联字段是否存在隐性的类型不匹配:比如数据库里外键列存的是
123(字符串类型),而主键列是数值类型的123,JPA查询时会因为类型不匹配找不到; - 如果你给
@ManyToOne加了optional = false,但关联字段存在null值,也会直接抛出这个异常,因为JPA要求必须找到关联实体。
四、JPA缓存的“过期数据”坑
如果之前删除过某个Beneficiaire实体,之后又重新插入了相同主键的实体,JPA的一级缓存(会话缓存)或者二级缓存可能还保留着旧的标记,导致查询时认为实体不存在。
解决办法:
- 调用
entityManager.clear()清除一级缓存; - 如果用了二级缓存,暂时关闭或者清空对应缓存区域再测试。
五、排查小技巧
- 开启JPA的SQL日志,直接看生成的SQL语句,把它复制到数据库客户端执行,看是否能查询到结果。在
application.yml里配置:
spring: jpa: show-sql: true properties: hibernate: format_sql: true
- 用
EntityManager的find方法直接查询Beneficiaire实体,比如entityManager.find(Beneficiaire.class, 你的主键值),排除是否是关联查询的问题。
内容的提问来源于stack exchange,提问作者Ibsea
相关产品推荐
相关产品推荐

