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

Spring Boot 2.7.16中JPA方法名自动生成查询异常排查

Spring Boot 2.7.16 JPA Repository 查询抛出 EntityNotFoundException 问题排查与解决

核心原因

  1. 数据不一致:数据库中存在AccessPlant记录关联的Plant实体已被删除(比如ID为12的Plant不存在,但AccessPlant中仍保留该ID的关联),JPA加载关联实体时触发异常。
  2. 关联加载策略变更:Spring Boot 2.x对应的Spring Data JPA/Hibernate版本升级后,关联实体的默认FetchType或加载逻辑发生变化。若AccessPlant中关联Plant的FetchType为EAGER,查询User时会强制加载关联的Plant,一旦Plant不存在就抛出异常。
  3. 查询逻辑隐性变化:
    • 自定义查询中LEFT OUTER JOIN后追加ap.accessPlantKey.plant.plantId IN (...)条件,实际将左连接转为内连接效果,仅返回存在匹配AccessPlant的User;若这些AccessPlant关联的Plant不存在,加载时触发异常。
    • 方法名自动生成的查询(如findAllByAccessPlantsSet_AccessPlantKey_Plant_PlantIdIn)在新版本中生成的SQL逻辑改变,默认尝试加载嵌套关联的Plant实体。
  4. 模糊匹配范围问题:精确匹配时返回的User对应的AccessPlant关联的Plant均存在,而模糊匹配返回的结果中包含关联了不存在Plant的User,触发加载异常。

解决办法

1. 清理脏数据(优先方案)

检查数据库中AccessPlant表的plant_id字段,删除或修复关联不存在Plant的记录。例如删除所有plant_id为12且对应的Plant不存在的AccessPlant记录,从根源解决数据不一致问题。

2. 调整关联加载策略

将AccessPlant中关联Plant的FetchType改为LAZY,避免查询User时自动加载Plant实体:

// AccessPlant类中关联Plant的字段
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "plant_id")
private Plant plant;

仅当业务逻辑主动访问plant属性时才会加载,避免不必要的关联加载触发异常。

3. 修改查询语句,避免加载关联实体

如果查询仅需使用Plant的ID做条件,无需加载Plant实体,直接使用AccessPlantKey中的plantId字段(假设是嵌入式主键的一部分),而非通过关联实体访问:

@Query("SELECT DISTINCT u FROM User u LEFT OUTER JOIN u.accessPlantsSet ap WHERE ap.accessPlantKey.plantId IN (?1)")
Page<User> findAllByPlantId(List<Long> plantIds, Pageable pageParam);

这样JPA不会尝试加载Plant实体,自然不会触发不存在的异常。

4. 使用Hibernate忽略不存在的关联(兼容方案)

若无法清理数据且需兼容脏数据,可使用Hibernate特有的@NotFound注解,忽略不存在的关联实体:

// AccessPlant类中关联Plant的字段
@ManyToOne
@NotFound(action = NotFoundAction.IGNORE)
private Plant plant;

此注解会让Hibernate将不存在的Plant设为null而非抛出异常,但会降低JPA的跨提供商兼容性,谨慎使用。

5. 修正左连接查询逻辑

若需保留左连接(允许返回无AccessPlant的User),调整WHERE条件处理ap为null的情况:

@Query("SELECT DISTINCT u FROM User u LEFT OUTER JOIN u.accessPlantsSet ap WHERE (?1 IS NULL OR ap.accessPlantKey.plant.plantId IN (?1))")
Page<User> findAllByPlantId(List<Long> plantIds, Pageable pageParam);

结合FetchType.LAZY使用,避免加载不存在的Plant实体。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 09:48:15