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);
}