在Spring Data JPA中引入Querydsl的实现方式

 更新时间:2021年01月30日 10:16:15   作者:闲丰  
这篇文章主要介绍了在Spring Data JPA中引入Querydsl的实现方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

一、环境说明

基础框架采用Spring Boot、Spring Data JPA、Hibernate。在动态查询中,有一种方式是采用Querydsl的方式。

二、具体配置

1、在pom.xml中,引入相关包和配置插件。

(1)引入包(注:不需要版本号,Spring Boot 会自动匹配合适的版本)

<!-- Querydsl相关包 -->  
  <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、设置源文件夹

经过上面pom.xml的配置后,就在 target/generated-sources 文件夹下面自动生成“查询对象”。需要将该文件夹设置成“源文件夹”,以便可以将下面的java文件进行编译使用。

生成的查询对象,都是在原实体(bo)类的名字前,加上 Q 表示。

3、dao中继承接口QueryDslPredicateExecutor

4、在service层使用 Querydsl方式进行是查询,例如:

三、写在最后

此文仅作为引入Querydsl的笔记,并不代表作者本人推荐使用Querydsl。就实际应用而言,个人更倾向于使用 JPA Criteria 的方式来实现动态查询,其接口是JpaSpecificationExecutor。

补充:Spring-data-jpa扩展查询 QueryDSL 实践

说明: QueryDSL是以函数连接的方式将SQL调用进行拆分,比较spring data jpa中的criteria查询方法还是简洁了不少。

用例:通过服务调用,使用querydsl进行查询并直接返回DTO对象(自定义传输对象(根据业务需求),注意区别于Entity)

实践步骤:

1.创建user与depart表,使用外键进行关联,并插入一些模拟数据。

2.创建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>节点下加入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.生成相关entity与repository对象,这里以user为例:

注意:repository需要继承 QueryDslPredicateExecutor<T>接口。

5.生成业务传输对象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.生成业务传输对象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.创建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进行查询,并直接转换需要的属性至DTO。并且代码中的pre是可以根据参数动态拼接的。

7.测试结果:

这是查询日志:

完。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

相关文章

  • 聊聊Java BigInteger里面的mod和remainder的区别

    聊聊Java BigInteger里面的mod和remainder的区别

    这篇文章主要介绍了聊聊Java BigInteger里面的mod和remainder的区别,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 如何集成swagger2构建Restful API

    如何集成swagger2构建Restful API

    这篇文章主要介绍了如何集成swagger2构建Restful API,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • 基于SpringBoot实现发送带附件的邮件

    基于SpringBoot实现发送带附件的邮件

    这篇文章主要介绍了基于SpringBoot实现发送带附件的邮件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • 浅谈spring-boot的单元测试中,@Before不被执行的原因

    浅谈spring-boot的单元测试中,@Before不被执行的原因

    这篇文章主要介绍了浅谈spring-boot的单元测试中,@Before不被执行的原因,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • java 定时器Timer和TimerTask的使用详解(执行和暂停)

    java 定时器Timer和TimerTask的使用详解(执行和暂停)

    这篇文章主要介绍了java 定时器Timer和TimerTask的使用详解(执行和暂停),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-11-11
  • JavaMail实现邮件发送的方法

    JavaMail实现邮件发送的方法

    这篇文章主要介绍了JavaMail实现邮件发送的方法,实例分析了java实现邮件发送的相关技巧,非常具有实用价值,需要的朋友可以参考下
    2015-04-04
  • Spark SQL 编程初级实践详解

    Spark SQL 编程初级实践详解

    这篇文章主要为大家介绍了Spark SQL 编程初级实践详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • Java中创建对象的5种方式总结

    Java中创建对象的5种方式总结

    本篇文章主要介绍了Java中创建对象的5种方式总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • Java设计模式之模板模式(Template模式)介绍

    Java设计模式之模板模式(Template模式)介绍

    这篇文章主要介绍了Java设计模式之模板模式(Template模式)介绍,定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中,需要的朋友可以参考下
    2015-03-03
  • hibernate存取json数据的代码分析

    hibernate存取json数据的代码分析

    这篇文章主要介绍了hibernate存取json数据的代码分析,需要的朋友可以参考下
    2017-09-09

最新评论