在Spring Data JPA中引入Querydsl的實(shí)現(xiàn)方式
一、環(huán)境說明
基礎(chǔ)框架采用Spring Boot、Spring Data JPA、Hibernate。在動(dòng)態(tài)查詢中,有一種方式是采用Querydsl的方式。
二、具體配置
1、在pom.xml中,引入相關(guān)包和配置插件。
(1)引入包(注:不需要版本號(hào),Spring Boot 會(huì)自動(dòng)匹配合適的版本)
<!-- Querydsl相關(guān)包 --> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-jpa</artifactId> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> </dependency>
(2)配置插件:主要用來生成“查詢對(duì)象”。
<plugin> <groupId>com.mysema.maven</groupId> <artifactId>maven-apt-plugin</artifactId> <version>1.0.4</version> <executions> <execution> <phase>generate-sources</phase> <goals> <goal>process</goal> </goals> <configuration> <outputDirectory>target/generated-sources</outputDirectory> <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor> </configuration> </execution> </executions> </plugin>
2、設(shè)置源文件夾
經(jīng)過上面pom.xml的配置后,就在 target/generated-sources 文件夾下面自動(dòng)生成“查詢對(duì)象”。需要將該文件夾設(shè)置成“源文件夾”,以便可以將下面的java文件進(jìn)行編譯使用。
生成的查詢對(duì)象,都是在原實(shí)體(bo)類的名字前,加上 Q 表示。

3、dao中繼承接口QueryDslPredicateExecutor

4、在service層使用 Querydsl方式進(jìn)行是查詢,例如:

三、寫在最后
此文僅作為引入Querydsl的筆記,并不代表作者本人推薦使用Querydsl。就實(shí)際應(yīng)用而言,個(gè)人更傾向于使用 JPA Criteria 的方式來實(shí)現(xiàn)動(dòng)態(tài)查詢,其接口是JpaSpecificationExecutor。
補(bǔ)充:Spring-data-jpa擴(kuò)展查詢 QueryDSL 實(shí)踐
說明: QueryDSL是以函數(shù)連接的方式將SQL調(diào)用進(jìn)行拆分,比較spring data jpa中的criteria查詢方法還是簡(jiǎn)潔了不少。
用例:通過服務(wù)調(diào)用,使用querydsl進(jìn)行查詢并直接返回DTO對(duì)象(自定義傳輸對(duì)象(根據(jù)業(yè)務(wù)需求),注意區(qū)別于Entity)
實(shí)踐步驟:
1.創(chuàng)建user與depart表,使用外鍵進(jìn)行關(guān)聯(lián),并插入一些模擬數(shù)據(jù)。

2.創(chuàng)建sprintboot項(xiàng)目,在pom文件中加入以下依賴:
<dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-jpa</artifactId> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> <scope>provided</scope> </dependency>
3.在pom文件中<build>--><plugins>節(jié)點(diǎn)下加入plugin:
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>4.1.3</version>
</dependency>
</dependencies>
</plugin>
4.生成相關(guān)entity與repository對(duì)象,這里以u(píng)ser為例:
注意:repository需要繼承 QueryDslPredicateExecutor<T>接口。
5.生成業(yè)務(wù)傳輸對(duì)象DTO:
package com.test.demo.db;
//
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
* User generated by hbm2java
*/
@Entity
@Table(name = "user", catalog = "testdb")
public class User implements java.io.Serializable {
private Integer id;
private Department department;
private String username;
public User() {
}
public User(Department department, String username) {
this.department = department;
this.username = username;
}
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fk_depart")
public Department getDepartment() {
return this.department;
}
public void setDepartment(Department department) {
this.department = department;
}
@Column(name = "username", length = 45)
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
}
package com.test.demo.repo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import org.springframework.stereotype.Repository;
import com.test.demo.db.User;
@Repository
public interface UserRepository extends QueryDslPredicateExecutor<User>, JpaRepository<User, Integer>,JpaSpecificationExecutor<User>{
}
注意:repository需要繼承 QueryDslPredicateExecutor<T>接口。
5.生成業(yè)務(wù)傳輸對(duì)象DTO:
package com.test.demo.controller;
import com.querydsl.core.annotations.QueryProjection;
import lombok.Data;
@SuppressWarnings("unused")
public @Data class UserDTO {
private String username;
private String departname;
}
6.創(chuàng)建controller進(jìn)行測(cè)試:
package com.test.demo.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.test.demo.db.QUser;
import com.test.demo.repo.UserRepository;
@RestController
@RequestMapping("/")
public class TestController {
@Autowired
UserRepository userRepo;
@Autowired
@PersistenceContext
EntityManager em;
private JPAQueryFactory queryFactory;
@PostConstruct
public void init() {
queryFactory = new JPAQueryFactory(em);
}
@RequestMapping("/users")
Object getUsers(@RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
@RequestParam(value = "size", required = false, defaultValue = "10") Integer size,
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "depart", required = false) String depart) {
QUser user = QUser.user;
JPAQuery<UserDTO> query = queryFactory
.select(Projections.bean(UserDTO.class, user.username, user.department.name.as("departname")))
.from(user);
BooleanExpression pre = null;
if (name!=null && !name.isEmpty()) {
pre = user.username.startsWith(name);
}
if (depart!=null && !depart.isEmpty()) {
pre = user.department.name.startsWith(depart);
}
query.where(pre);
query.limit(size);
query.offset((page-1)*size);
List<UserDTO> result = query.fetch();
Map<String, Object> map = new HashMap<>();
map.put("total", userRepo.count(pre));
map.put("data", result);
return map;
}
}
注:這里就是使用querydsl進(jìn)行查詢,并直接轉(zhuǎn)換需要的屬性至DTO。并且代碼中的pre是可以根據(jù)參數(shù)動(dòng)態(tài)拼接的。
7.測(cè)試結(jié)果:

這是查詢?nèi)罩荆?/p>

完。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
HttpClient POST請(qǐng)求第三方接口問題(多參數(shù)傳參)
這篇文章主要介紹了HttpClient POST請(qǐng)求第三方接口問題(多參數(shù)傳參),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
java WebSocket的實(shí)現(xiàn)以及Spring WebSocket示例代碼
本篇文章主要介紹了java WebSocket的實(shí)現(xiàn)以及Spring WebSocket,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-01-01
Java遠(yuǎn)程調(diào)用組件Feign技術(shù)使用詳解
Feign是Netflix公司開發(fā)的一個(gè)聲明式的REST調(diào)用客戶端; Ribbon負(fù)載均衡、 Hystrⅸ服務(wù)熔斷是我們Spring Cloud中進(jìn)行微服務(wù)開發(fā)非?;A(chǔ)的組件,在使用的過程中我們也發(fā)現(xiàn)它們一般都是同時(shí)出現(xiàn)的,而且配置也都非常相似2022-11-11
解決IDEA中下載free maven plugin插件無效的問題
這篇文章主要介紹了解決IDEA中下載free maven plugin插件無效的問題,本文通過圖文并茂的形式給大家分享解決方案,供大家參考,需要的朋友可以參考下2020-11-11
java開發(fā)之讀寫txt文件操作的實(shí)現(xiàn)
本篇文章介紹了,java開發(fā)之讀寫txt文件操作的實(shí)現(xiàn)。需要的朋友參考下2013-05-05
java接入創(chuàng)藍(lán)253短信驗(yàn)證碼的實(shí)例講解
下面小編就為大家分享一篇java接入創(chuàng)藍(lán)253短信驗(yàn)證碼的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-01-01

