利用JPA+querydsl实现多条件动态查询

相信很多人在做订单管理的时候会用到多条件的检索,比如说查询订单状态是已支付的,金额在100-200之间的商铺a的已完结的订单,这样的多条件。
实现方式有多种,核心就一个if和判空。今天学习了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版实体类。
在这里插入图片描述

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

@Bean
	public 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;

/**
 * author by 李兆杰
 * Date 2018/11/28
 */
@Data
public 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,我们了解一下这个特殊的返回类型
看源码
results是返回的list数据数组
total是总数
offset是从哪开始
limit是限制条数

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

整个查询就完成了,怎么去渲染数据就看大家喜好了。文笔有限,欢迎吐槽,谢谢阅读

  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值