文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

怎么使用JPA+querydsl实现多条件动态查询

2023-06-29 11:33

关注

这篇文章将为大家详细讲解有关怎么使用JPA+querydsl实现多条件动态查询,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

JPA querydsl多条件动态查询

相信很多人在做订单管理的时候会用到多条件的检索,比如说查询订单状态是已支付的,金额在100-200之间的商铺a的已完结的订单,这样的多条件。

实现方式有多种,核心就一个if和判空。今天学习了querydsl,来具体回顾一下。

首先是我做的效果图,我们主要看查询怎么实现的。

怎么使用JPA+querydsl实现多条件动态查询

介绍一下querydsl

首先QueryDSL仅仅是一个通用的查询框架,专注于通过Java API构建类型安全的SQL查询。

其次Querydsl可以通过一组通用的查询API为用户构建出适合不同类型ORM框架或者是SQL的查询语句,也就是说QueryDSL是基于各种ORM框架以及SQL之上的一个通用的查询框架。

再然后借助QueryDSL可以在任何支持的ORM框架或者SQL平台上以一种通用的API方式来构建查询。目前QueryDSL支持的平台包括JPA,JDO,SQL,Java Collections,RDF,Lucene,Hibernate Search。

开始开发 ,首先是pom依赖

这里要加两个关于querydsl的依赖,jpa和apt,版本是一致的

<dependency><groupId>com.querydsl</groupId><artifactId>querydsl-jpa</artifactId><version>4.2.1</version></dependency><dependency><groupId>com.querydsl</groupId><artifactId>querydsl-apt</artifactId><version>4.2.1</version></dependency>

然后是要配置一个插件来生成Q版的实体类,只有Q版的实体类才能参与querydsl的查询

<plugin><groupId>com.querydsl</groupId><artifactId>querydsl-maven-plugin</artifactId><executions><execution><phase>generate-sources</phase><goals><goal>jpa-export</goal></goals><configuration><targetFolder>target/generated-sources/java</targetFolder><packages>com.jerry.gamemarket.entity</packages></configuration></execution></executions></plugin>
<targetFolder>target/generated-sources/java</targetFolder>

这是生成Q版实体的目标文件夹

<packages>com.jerry.gamemarket.entity</packages>

这是把那些包下的实体生成Q版。 

执行mvn compile之后,就能看到生成Q版实体类。

怎么使用JPA+querydsl实现多条件动态查询

在编写具体的查询方法之前我们需要实例化EntityManager对象以及JPAQueryFactory对象,并且通过实例化控制器时就去实例化JPAQueryFactory对象,所以在启动类中引入一个Bean叫JPAQueryFactory加一个EntityManager参数,可以全局使用。

@Beanpublic JPAQueryFactory queryFactory(EntityManager entityManager){return new JPAQueryFactory(entityManager);}

搜索条件实体类

package com.jerry.gamemarket.dto;import com.jerry.gamemarket.enums.OrderStatusEnums;import com.jerry.gamemarket.enums.PayStatusEnums;import lombok.Data;import org.springframework.context.annotation.Bean;import java.math.BigDecimal;@Datapublic class SearchOrderDTO {    private  String orderId;    //   private String id;    private  String buyerName;    private  String buyerPhone;    private  String buyerAddress;    private  String canteenName;    private BigDecimal maxAmount;    private BigDecimal minAmount;    private Integer orderStatus;    //    默认未支付    private Integer payStatus;    private Integer pageNum = 1;    private Integer pageSize=10;}

动态搜索实现类中的方法,这里返回类型是 QueryResults,我们了解一下这个特殊的返回类型

看源码

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)//package com.querydsl.core;import com.google.common.collect.ImmutableList;import java.io.Serializable;import java.util.List;import javax.annotation.Nullable;public final class QueryResults<T> implements Serializable {    private static final long serialVersionUID = -4591506147471300909L;    private static final QueryResults<Object> EMPTY = new QueryResults(ImmutableList.of(), 9223372036854775807L, 0L, 0L);    private final long limit;    private final long offset;    private final long total;    private final List<T> results;    public static <T> QueryResults<T> emptyResults() {        return EMPTY;    }    public QueryResults(List<T> results, @Nullable Long limit, @Nullable Long offset, long total) {        this.limit = limit != null ? limit.longValue() : 9223372036854775807L;        this.offset = offset != null ? offset.longValue() : 0L;        this.total = total;        this.results = results;    }    public QueryResults(List<T> results, QueryModifiers mod, long total) {        this(results, mod.getLimit(), mod.getOffset(), total);    }    public List<T> getResults() {        return this.results;    }    public long getTotal() {        return this.total;    }    public boolean isEmpty() {        return this.results.isEmpty();    }    public long getLimit() {        return this.limit;    }    public long getOffset() {        return this.offset;    }}
 @Override    public QueryResults<OrderMaster> dymamicQuery(SearchOrderDTO searchOrderDTO) {        QOrderMaster o = QOrderMaster.orderMaster;        JPAQuery<OrderMaster> query = jpaQueryFactory.select(o).from(o);        if (!StringUtils.isEmpty(searchOrderDTO.getOrderId())){            query.where(o.orderId.like(searchOrderDTO.getOrderId()));        }        if (!StringUtils.isEmpty(searchOrderDTO.getBuyerName())){            query.where(o.buyerName.like("%"+searchOrderDTO.getBuyerName()+"%"));        }        if (!StringUtils.isEmpty(searchOrderDTO.getBuyerPhone())){            query.where(o.buyerPhone.eq(searchOrderDTO.getBuyerPhone()));        }        if (searchOrderDTO.getMaxAmount()!=null && searchOrderDTO.getMinAmount()!=null){            query.where(o.orderAmount.goe(searchOrderDTO.getMinAmount()));        }        if (searchOrderDTO.getMaxAmount()!=null && searchOrderDTO.getMinAmount()!=null){            query.where(o.orderAmount.loe(searchOrderDTO.getMaxAmount()));        }        if (searchOrderDTO.getOrderStatus()!=null){            query.where(o.orderStatus.eq(searchOrderDTO.getOrderStatus()));        }        if (searchOrderDTO.getPayStatus()!=null){            query.where(o.payStatus.eq(searchOrderDTO.getPayStatus()));        }        return query.orderBy(o.createTime.desc())                .offset((searchOrderDTO.getPageNum()-1)*searchOrderDTO.getPageSize())                .limit(searchOrderDTO.getPageSize())                .fetchResults();    }

这些查询中包含了模糊查询,动态查询和分页

最后是Controller中的引用

@PostMapping("/searchorder")    public QueryResults<OrderMaster> findByCase(@RequestBody SearchOrderDTO searchOrderDTO){        QueryResults<OrderMaster> queryResults=orderService.dymamicQuery(searchOrderDTO);        System.out.println(searchOrderDTO);        System.out.println(queryResults.getResults());        return queryResults;    }

整个查询就完成了,怎么去渲染数据就看大家喜好了。

springdataJPA和querydsl

什么是SpringDataJPA?什么是QueryDSL?

SpringDataJPA是对JPA使用的封装(JPA是java持久层api)

QueryDSL是基于各种ORM(对象关系映射)上的一个通用框架。使用其API类库,可以写出java代码的sql

@Mapper 实体-模型映射

在mapper上使用注解 @Mapper(componentModel = "spring", uses = {})

用于映射dto和entity 自动生成mapper实现 完成相互转化

如果dto和entity中的属性名不匹配,需要增加注解

@Mappings({@Mapping(source = "entity.name", target = "dto属性名")})

项目整体流程

服务后台中rest包下对外暴露提供restful接口,具体类中引入代理层,该代理层实现dto以及dao层的处理(注入service以及自动生成的mapper映射),由mapper处理dto与entity之间的相互转化,service层操作db(操作方式为jpa)

疑问

代理类中,为什么要通过在构造方法上增加@Autowired注解对mapper和service进行初始化,而不是对要注入的成员变量上增加@Autowired注解,采用构造方法的方式有何优点?

通过相关资料找到其答案:java变量初始化的顺序为:静态变量或静态语句块&ndash;>实例变量或初始化语句块&ndash;>构造方法&ndash;>@Autowired 如果该类中有增加构造方法时,执行构造方法时,成员变量还没有初始化,此时会报错,如果没有构造方法可以在成员变量上增加@Autowired注解来初始化变量。为了避免构造方法初始化的时候,成员变量还没有初始化,所以建议在构造方法上增加@Autowired注解。

项目中QueryDSL仅用于生成q类,并没有用java代码格式的sql呀?为什么只用了spring-data-jpa?

JpaRepository

spring-data-jpa简介,spring整合各种第三方框架,命名格式为spring-data-*,spring整合jpa造就了spring-data-jpa。

repository就是持久层,相当于dao、mapper等,项目中定义各种repository继承JpaRepository就可以使用基本的CRUD。

怎么使用JPA+querydsl实现多条件动态查询

CrudRepository该接口是spring整合jpa的二级接口,此接口提供了普通的CRUD操作,后续新增PagingAndSortingRepository接口,提供findAll方法的重载方法(支持分页),QueryByExampleExecutor优雅的解决了空指针问题,后续优化为JpaRepository接口,该接口对上个接口方法进行优化,返回值更广泛。

SimpleJpaRepository

该类是JpaRepository接口的具体实现,CRUD操作就是由该类提供的。包括四个成员变量JpaEntityInformation、PersistenceProvider、CrudMethodMetadata、EntityManager。 前三个成员变量是为了获取拼接sql,EntityManager执行该sql。相当于session、sqlSession等

写一个Repository继承JpaRepository之后

可以写其实现类,但是不需要implements关键字去实现,spring-data-jpa会自动识别其关系,也可以不写实现类,在运行时期,SimpleJpaRepository该类就是其实现类,如果写了自定义实现类,就会执行实现类中的逻辑

spring-data-jpa的相关语法

怎么使用JPA+querydsl实现多条件动态查询

对于多表查询 需要用到Specification匿名内部类,重写其方法。感觉遇到多表查询还是写sql比较直观

关于“怎么使用JPA+querydsl实现多条件动态查询”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯