首页 > 编程语言 >jpa2.2.10 JpaSpecificationExecutor Specification 查询时,实体类中存在@OneToMany,怎么才能查询的时候不查询该@OneToMany的关联表?

jpa2.2.10 JpaSpecificationExecutor Specification 查询时,实体类中存在@OneToMany,怎么才能查询的时候不查询该@OneToMany的关联表?

时间:2023-06-17 09:02:08浏览次数:59  
标签:10 String OneToMany cb 查询 root fetch name

对于这个问题,您可以在查询时通过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

相关文章

  • 专业版 win10 激活
    powershell内,运行如下命令wmicpathSoftwareLicensingServicegetOA3xOriginalProductKey按回车键,即可看到格式为XXXXX-XXXXX-XXXXX-XXXXX-XXXXX的产品密钥。更改产品密钥:输入查找到的产品密钥.发现激活不成功.更改dns4.2.2.1  4.2.2.2,去掉IPV6,重启后,再次 疑难解答 激......
  • 分享10个有趣的AI小工具
    随着ChatGPT的问世,AI也算迎来了高光时刻!下文是技术宅整理的一些和ChatGPT相关的工具应用,排名不分先后,也不代表个人推荐,但真心真心好好用,主打的就是一个纯粹!本文将先分享10个有趣的AI小工具,最后3个小工具,是我们搬砖人心心念念的。建议收藏、转发、保存!工具名称地址工具说明......
  • 2023.6.16 10.数据库备份恢复
    10.数据库备份恢复1.MySQL逻辑备份与恢复1.1数据库完整备份与恢复1.2数据库增量备份与恢复2.MySQL物理备份与恢复2.1数据库完整备份与恢复2.2数据库增量备份与恢复2.3数据库差异备份与恢复3.简单命令进⾏物理备份4.⽣产备份思路与实战 通常数据库备份database数据......
  • mysql 子查询
    什么是子查询一个select语句中包含另一个完整的select语句,或两个以上SELECT。子select可以出现在where后面,当作一个查询条件使用;或者出现在from后面,作为一个新表单供查询使用。#创建部门表CREATETABLE`dept`(`deptno`bigint(2)NOTNULLAUTO_INCREMENTCOMMENT'表示......
  • 1100. 抓住那头牛(bfs)
    https://www.acwing.com/problem/content/1102/数据范围为1e5实际上还可以再继续细分,加入特判来优化耗时,但是意义不大#include<iostream>#include<cstring>#include<cstdio>#include<queue>usingnamespacestd;constintN=1e5+10;intn,k;boolvis[N];int......
  • windows10 安装Ubuntu
    1.windows应用商店下载wsl。 2. windows应用商店下载Ubuntu。 3.启用windows虚拟机搜索栏搜索windows功能(windowsfeatures) 4.打开window虚拟机和subsystemforlinux。然后重启 5.打开步骤2下载的Ubuntu开始安装  ......
  • 域名解析之递归查询VS迭代查询
    【大部分内容转自中科三方】DNS解析是互联网中的重要环节,承担着将域名翻译为可由计算机直接读取的IP地址的基础功能。根据查询对象不同DNS解析可分为递归解析和迭代解析两种方式什么是递归查询?“递归解析”是最常见也是默认的一种解析方式。在这种解析方式中,如果客户端配......
  • 【React工作记录一百零九】前端小知识点扫盲笔记记录10
    前言我是歌谣放弃很容易但是坚持一定很酷微信公众号关注前端小歌谣带你进入前端巅峰交流群今天继续对前端知识的小结对称数<!DOCTYPEhtml><htmllang="en"> <head> <metacharset="UTF-8"/> <metahttp-equiv="X-UA-Compatible"content="IE=edge"/>......
  • Python设计模式-10-享元模式
    享元模式是一种结构型设计模式,它通过共享对象来减少内存使用和对象创建的数量。享元模式通常包括以下几个角色:享元工厂(FlyweightFactory):负责创建和管理享元对象。享元(Flyweight):表示共享的对象,包含内部状态和外部状态。内部状态(IntrinsicState):存储在享元对象内部的状态,不会随......
  • 101 显示数组中的大写字母 小写字母 数字
    packagecom.fqs.demo001;importjava.util.Scanner;publicclassCompare{publicstaticvoidmain(String[]args){//键盘录入一个字符串,统计该字符串大写字母字符,小写字母字符,数字字符出现的次数//比如ABCabc123Scannersc=newScanner(......