在Spring Data JPA中引入Querydsl的實(shí)現(xiàn)方式
基礎(chǔ)框架采用Spring Boot、Spring Data JPA、Hibernate。在動(dòng)態(tài)查詢中,有一種方式是采用Querydsl的方式。
二、具體配置1、在pom.xml中,引入相關(guān)包和配置插件。
(1)引入包(注:不需要版本號,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)配置插件:主要用來生成“查詢對象”。
<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)生成“查詢對象”。需要將該文件夾設(shè)置成“源文件夾”,以便可以將下面的java文件進(jìn)行編譯使用。
生成的查詢對象,都是在原實(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查詢方法還是簡潔了不少。
用例:通過服務(wù)調(diào)用,使用querydsl進(jìn)行查詢并直接返回DTO對象(自定義傳輸對象(根據(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對象,這里以user為例:
注意:repository需要繼承 QueryDslPredicateExecutor<T>接口。
5.生成業(yè)務(wù)傳輸對象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;@Repositorypublic interface UserRepository extends QueryDslPredicateExecutor<User>, JpaRepository<User, Integer>,JpaSpecificationExecutor<User>{ }
注意:repository需要繼承 QueryDslPredicateExecutor<T>接口。
5.生成業(yè)務(wù)傳輸對象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)行測試:
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.測試結(jié)果:
這是查詢?nèi)罩荆?/p>
完。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章:
1. python 編寫輸出到csv的操作2. 利用原生JS實(shí)現(xiàn)歡樂水果機(jī)小游戲3. js的一些潛在規(guī)則使用分析4. 淺談SpringMVC jsp前臺(tái)獲取參數(shù)的方式 EL表達(dá)式5. JAMon(Java Application Monitor)備忘記6. Python PyQt5-圖形界面的美化操作7. PHP swoole的process模塊創(chuàng)建和使用子進(jìn)程操作示例8. IntelliJ IDEA 常用設(shè)置(配置)吐血整理(首次安裝必需)9. php中加密解密DES類的簡單使用方法示例10. python用moviepy對視頻進(jìn)行簡單的處理
