jpa Specification fetch查询报错,query specified join fetching, but the owner of the fetched association

本文详细介绍了在使用 JPA Specification 进行复杂查询时遇到的 'query specified join fetching, but the owner of the fetched association was not present in the select' 错误,以及如何通过 fetch 操作来优化查询性能。通过示例展示了如何在 Specification 中正确使用 root.fetch() 方法,同时讲解了 @OneToOne 关联导致的查询效率低下问题,并给出了使用 FetchType.LAZY 和 @NamedEntityGraph 结合 EntityGraph 注解的解决方案,以避免额外的 SQL 查询。此外,还提到了在分页查询时如何避免 count 中缺少 fetch 字段导致的错误,以及在 Specification 中添加条件判断来确保查询的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

jpa Specification fetch查询报错,query specified join fetching, but the owner of the fetched association was not present in the select

jpa Specification fetch查询报错,query specified join fetching, but the owner of the fetched association was not present in the select

使用jpa Specification 使用fetch查询时报错query specified join fetching, but the owner of the fetched association was not present in the select。

  root.fetch("xxxxxxxx", JoinType.LEFT);

若使用:Pageable进行分页查询时,在sqec里打断点会触发两次

Pageable pageable=PageRequest.of(current - Constants.1, pageSize, sort);
xxxRepository.findAll(spec, pageable);

通过打印sql发现,jpa查询了两次,一次记录查询,一次count 。
当查询结果数量超过一页时,jpa需要通过count语句查询数量。
此时count中不存在fetch指定的字段导致报错。
故需要增加判断条件,第二次经过断点查询count。当查询结果为Long时跳过。

  if (!criteriaQuery.getResultType().equals(Long.class)) {
      root.fetch("controlRate", JoinType.LEFT);
     }

使用fetch的原因

查询entity中使用了@OneToOne 一对一关联,导致jpa查询缓慢,查询sql增多,出现n+1的性能问题。

    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "ccc", referencedColumnName = "id")
    private xxxEntity entity;

此时需要将急加载更换为懒加载,并在entity上方使用@NamedEntityGraph , 解决查询sql过多的问题。
entity:@NamedEntityGraph

	@NamedEntityGraph(name="xxxx.all",attributeNodes={@NamedAttributeNode("xxxEntity")})

	...
	
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "ccc", referencedColumnName = "id")
    private xxxEntity entity;

repository中添加注解 @EntityGraph

@Repository
public interface xxxRepository extends JpaRepository<xxxEntity , Long>, JpaSpecificationExecutor<Long>  {
    /**
     * 通过Name查找
     *
     * @param name  name
     * @return 对象
     */
    @EntityGraph(value = "xxxx.all" , type= EntityGraph.EntityGraphType.FETCH)
    xxxEntity findByName(String name);
    }

可避免查询时产生过多sql语句的问题。
此时需关注使用Specification 查询的方法,Specification 中需增加 root.fetch(“字段名称” , “左连接”)完成级联查询。

 Specification<LoopEntity> spec = (root, criteriaQuery, criteriaBuilder) -> {
	 ...
	  if (!criteriaQuery.getResultType().equals(Long.class)) {
	      root.fetch("entity", JoinType.LEFT);
     }
	 ... 
     criteriaQuery.where(predicate);
     }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值