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

3、dao中繼承接口QueryDslPredicateExecutor

4、在service層使用 Querydsl方式進行是查詢,例如:

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

2.創(chuàng)建sprintboot項目,在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é)點下加入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對象,這里以user為例:
注意:repository需要繼承 QueryDslPredicateExecutor<T>接口。
5.生成業(yè)務傳輸對象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è)務傳輸對象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進行測試:
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進行查詢,并直接轉(zhuǎn)換需要的屬性至DTO。并且代碼中的pre是可以根據(jù)參數(shù)動態(tài)拼接的。
7.測試結(jié)果:

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

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

