欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用JPA+querydsl如何實現(xiàn)多條件動態(tài)查詢

 更新時間:2022年03月12日 14:56:25   作者:ifJerry  
這篇文章主要介紹了使用JPA+querydsl如何實現(xiàn)多條件動態(tài)查詢,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

JPA querydsl多條件動態(tài)查詢

相信很多人在做訂單管理的時候會用到多條件的檢索,比如說查詢訂單狀態(tài)是已支付的,金額在100-200之間的商鋪a的已完結的訂單,這樣的多條件。

實現(xiàn)方式有多種,核心就一個if和判空。今天學習了querydsl,來具體回顧一下。

首先是我做的效果圖,我們主要看查詢怎么實現(xiàn)的。

在這里插入圖片描述

介紹一下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。

開始開發(fā) ,首先是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版。 

執(zhí)行mvn compile之后,就能看到生成Q版實體類。

在這里插入圖片描述

在編寫具體的查詢方法之前我們需要實例化EntityManager對象以及JPAQueryFactory對象,并且通過實例化控制器時就去實例化JPAQueryFactory對象,所以在啟動類中引入一個Bean叫JPAQueryFactory加一個EntityManager參數(shù),可以全局使用。

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

動態(tài)搜索實現(xiàn)類中的方法,這里返回類型是 QueryResults,我們了解一下這個特殊的返回類型

看源碼

  • results是返回的list數(shù)據(jù)數(shù)組
  • total是總數(shù)
  • offset是從哪開始
  • limit是限制條數(shù)
//
// 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();
    }

這些查詢中包含了模糊查詢,動態(tài)查詢和分頁

最后是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;
    }

整個查詢就完成了,怎么去渲染數(shù)據(jù)就看大家喜好了。

springdataJPA和querydsl

什么是SpringDataJPA?什么是QueryDSL?

SpringDataJPA是對JPA使用的封裝(JPA是java持久層api)

QueryDSL是基于各種ORM(對象關系映射)上的一個通用框架。使用其API類庫,可以寫出java代碼的sql

@Mapper 實體-模型映射

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

用于映射dto和entity 自動生成mapper實現(xiàn) 完成相互轉化

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

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

項目整體流程

服務后臺中rest包下對外暴露提供restful接口,具體類中引入代理層,該代理層實現(xiàn)dto以及dao層的處理(注入service以及自動生成的mapper映射),由mapper處理dto與entity之間的相互轉化,service層操作db(操作方式為jpa)

疑問

代理類中,為什么要通過在構造方法上增加@Autowired注解對mapper和service進行初始化,而不是對要注入的成員變量上增加@Autowired注解,采用構造方法的方式有何優(yōu)點?

通過相關資料找到其答案:java變量初始化的順序為:靜態(tài)變量或靜態(tài)語句塊–>實例變量或初始化語句塊–>構造方法–>@Autowired 如果該類中有增加構造方法時,執(zhí)行構造方法時,成員變量還沒有初始化,此時會報錯,如果沒有構造方法可以在成員變量上增加@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。

CrudRepository該接口是spring整合jpa的二級接口,此接口提供了普通的CRUD操作,后續(xù)新增PagingAndSortingRepository接口,提供findAll方法的重載方法(支持分頁),QueryByExampleExecutor優(yōu)雅的解決了空指針問題,后續(xù)優(yōu)化為JpaRepository接口,該接口對上個接口方法進行優(yōu)化,返回值更廣泛。

SimpleJpaRepository

該類是JpaRepository接口的具體實現(xiàn),CRUD操作就是由該類提供的。包括四個成員變量JpaEntityInformation、PersistenceProvider、CrudMethodMetadata、EntityManager。 前三個成員變量是為了獲取拼接sql,EntityManager執(zhí)行該sql。相當于session、sqlSession等

寫一個Repository繼承JpaRepository之后

可以寫其實現(xiàn)類,但是不需要implements關鍵字去實現(xiàn),spring-data-jpa會自動識別其關系,也可以不寫實現(xiàn)類,在運行時期,SimpleJpaRepository該類就是其實現(xiàn)類,如果寫了自定義實現(xiàn)類,就會執(zhí)行實現(xiàn)類中的邏輯

spring-data-jpa的相關語法

對于多表查詢 需要用到Specification匿名內(nèi)部類,重寫其方法。感覺遇到多表查詢還是寫sql比較直觀

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • 五分鐘帶你快速學習Spring?IOC

    五分鐘帶你快速學習Spring?IOC

    這篇文章主要給大家介紹了關于如何通過五分鐘快速學習Spring?IOC的相關資料,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2022-03-03
  • 用Java實現(xiàn)全國天氣預報的api接口調(diào)用示例

    用Java實現(xiàn)全國天氣預報的api接口調(diào)用示例

    查詢天氣預報在APP中常用的一個常用功能,本文實例講述了java調(diào)用中國天氣網(wǎng)api獲得天氣預報信息的方法。分享給大家供大家參考。
    2016-10-10
  • java基于jdbc連接mysql數(shù)據(jù)庫功能實例詳解

    java基于jdbc連接mysql數(shù)據(jù)庫功能實例詳解

    這篇文章主要介紹了java基于jdbc連接mysql數(shù)據(jù)庫功能,結合實例形式詳細分析了jdbc連接mysql數(shù)據(jù)庫的原理、步驟、實現(xiàn)方法及相關操作技巧,需要的朋友可以參考下
    2017-10-10
  • SpringBoot設置接口超時的方法小結

    SpringBoot設置接口超時的方法小結

    這篇文章主要介紹了SpringBoot設置接口超時的方法小結,包括配置文件,config配置類及相關示例代碼,代碼簡單易懂,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • Jmeter對接口測試入?yún)崿F(xiàn)MD5加密

    Jmeter對接口測試入?yún)崿F(xiàn)MD5加密

    這篇文章主要介紹了Jmeter對接口測試入?yún)崿F(xiàn)MD5加密,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • Java實現(xiàn)多叉樹和二叉樹之間的互轉

    Java實現(xiàn)多叉樹和二叉樹之間的互轉

    本文主要介紹了Java實現(xiàn)多叉樹和二叉樹之間的互轉,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-05-05
  • SpringBoot自動配置的實現(xiàn)原理

    SpringBoot自動配置的實現(xiàn)原理

    這篇文章主要介紹了詳解SpringBoot自動配置原理,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • Java httpClient連接池支持多線程高并發(fā)的實現(xiàn)

    Java httpClient連接池支持多線程高并發(fā)的實現(xiàn)

    本文主要介紹了Java httpClient連接池支持多線程高并發(fā)的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • springboot集成JWT實現(xiàn)身份認證(權鑒)的方法步驟

    springboot集成JWT實現(xiàn)身份認證(權鑒)的方法步驟

    本文主要介紹了springboot集成JWT實現(xiàn)身份認證(權鑒)的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-04-04
  • JavaWeb實現(xiàn)mysql數(shù)據(jù)庫數(shù)據(jù)的添加和刪除

    JavaWeb實現(xiàn)mysql數(shù)據(jù)庫數(shù)據(jù)的添加和刪除

    這篇文章主要介紹了如何利用JavaWeb實現(xiàn)mysql數(shù)據(jù)庫數(shù)據(jù)的添加和刪除功能,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下
    2022-03-03

最新評論