对于这个问题,您可以在查询时通过join()方法指定不查询@OneToMany关联表。
举个例子,如果有一个实体A与实体B是一对多关系,那么您可以这样写查询条件:
@OneToMany(targetEntity = DcyRightImage.class,cascade = {CascadeType.ALL},fetch = FetchType.EAGER) @JoinColumn(name = "geo_id", referencedColumnName = "id") private Set<DcyRightImage> images; @OneToMany(targetEntity = DcyRightVideo.class,cascade = {CascadeType.ALL},fetch = FetchType.EAGER) @JoinColumn(name = "geo_id", referencedColumnName = "id") private Set<DcyRightVideo> videos;
public static Specification webRightConditionSpecification(String code, String name, String land, String remark1, Date createdTime, String releaseStatus, String geo) { Specification<Object> specification = (Specification<Object>) (root, criteriaQuery, cb) -> { List<Predicate> predicates = new ArrayList<>(); predicates.add(cb.equal(root.get("deleted"), 0)); //通过JoinType方法 指定不查询@OneToMany关联表, lt ,2023.06.17 if (!criteriaQuery.getResultType().equals(Long.class)) //jpa查询了两次,一次记录查询,一次count 。当查询结果数量超过一页时,jpa需要通过count语句查询数量。此时count中不存在fetch指定的字段导致报错。要增加判断条件,第二次经过断点查询count。当查询结果为Long时跳过。 { root.fetch("images", JoinType.LEFT); //指定不查询关联表 ,注意,此关键词为实体类中的表属性名称 root.fetch("videos", JoinType.LEFT); ////指定不查询关联表 ,注意,此关键词为实体类中的表属性名称 } // 查询已经发布的桥梁信息 if (geo != null) { LiteralExpression<String> regitsterAdressExp = new LiteralExpression<>(null, geo); // 函数名称,返回值类型ST_Intersects(geo,table.gep) Expression<Boolean> similarityFunc = cb.function("ST_Intersects",Boolean.class,regitsterAdressExp, root.get("geo")); predicates.add(cb.isTrue(similarityFunc)); } if (createdTime != null) { predicates.add(cb.greaterThan(root.get("createdTime"), createdTime)); } if (StringUtils.isNoEmpty(remark1)) { predicates.add(cb.or(cb.like(root.get("remark1").as(String.class),"%"+ remark1 + "%"))); } if (StringUtils.isNoEmpty(releaseStatus)) { predicates.add(cb.equal(root.get("releaseStatus"), PublicParam.HAVE_RELEASE)); } if (StringUtils.isNoEmpty(code)) { predicates.add(cb.or(cb.like(root.get("code").as(String.class),"%"+ code + "%"))); } if (StringUtils.isNoEmpty(name)) { predicates.add(cb.or(cb.like(root.get("rightobligee").as(String.class),"%"+ name + "%"))); predicates.add(cb.or(cb.like(root.get("rightcardno").as(String.class),"%"+ name + "%"))); } if (StringUtils.isNoEmpty(land)) { predicates.add(cb.or(cb.like(root.get("land").as(String.class),"%"+ land + "%"))); } return cb.and(predicates.toArray(new Predicate[0])); }; return specification; }
使用心得一:当分页查询时,如下:
public EasyPage selectDcyDict(String code, String name, String land, String remark1, Date createdTime, String releaseStatus, String geo, Pageable pageable) { // 获取查询条件 Specification specification = QueryCriteriaUtil.webConditionSpecification(code, name, land, remark1,createdTime,releaseStatus, geo); Page page = repository.findAll(specification,pageable); return new EasyPage<DcyDict>(page); }
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); }
使用心得二:当分页查询时,如下:
查询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,String,OneToMany,cb,查询,root,fetch,name From: https://www.cnblogs.com/Fooo/p/17486994.html