QueryDSL和Spring Data JPA动态查询实践

目录

1.背景

2.QueryDSL简介

3.配置步骤

3.1 pom配置

3.2 添加maven插件

3.3 项目JPA基本配置

3.4 实体类注解配置

4后端写法

4.1持久层写法

4.2服务层写法

4.3控制层写法

5.致谢


1.背景

      项目后端数据持久化之前使用的是JPA的JPQL写法,而JPQL不支持 insert、limit等sql常用函数,给开发造成诸多不便。因此,我们常常使用native sql形式来书写sql语句,来查询和组装我们需要的数据,但是根据实际项目需求,需要灵活选用Mysql、Microsoft sqlserver、Postgresql等数据库管理系统。那么无论是JPQL或者是native sql的写法,在数据库更换后,很容易带来一定的兼容性问题。

2.QueryDSL简介

      QueryDSL是一个通用的查询框架,专注于通过 JavaAPI 构建类型安全的 Sql 查询,也可以说 QueryDSL 是基于各种 ORM 框架以及 Sql 之上的一个通用的查询框架,使用它的API类库可以写出“Java代码的sql”,不用去手动接触sql语句,表达含义却如sql般准确。更重要的一点,我们可以SpringDataJPA + QueryDSL JPA联合使用,它们之间有着完美的相互支持,以达到更高效的编码。

3.配置步骤

       本次配置基于SpringBoot 2.1.4.RELEASE版本

3.1 pom配置



    com.querydsl
    querydsl-jpa


    com.querydsl
    querydsl-apt
    provided

3.2 添加maven插件


    com.mysema.maven
    apt-maven-plugin
    1.1.3
    
        
            
                process
            
            
                target/generated-sources/java
                com.querydsl.apt.jpa.JPAAnnotationProcessor
            
        
    

        添加这个插件是为了生成实体对应的查询类(查询实体,命名方式为:"Q"+对应实体名)。

3.3 项目JPA基本配置

目前后端使用Nacos发现、配置和管理项目下的各种微服务,在本地开发平台64上有个are-common.yaml作为项目的统一配置的规约,关于JPA的配置如下:

spring:
  returnvaluehandlerproxy:
    active: "true"
  jpa:
    #项目目前使用的database为postgresql
    database: postgresql
    show-sql: true
    properties:
      open-in-view: true
      hibernate:
        dialect: org.hibernate.dialect.PostgreSQLDialect
        temp:
          use_jdbc_metadata_defaults: false
        hbm2ddl:
          auto: update

3.4 实体类注解配置

在项目java实体类中必须标注注解@Entity,否则apt插件生成查询类失败

4后端写法

在此,介绍各个分层的写法,只是做个样例,大家理解它的思路即可。

4.1持久层写法

import com.abc.mare.common.util.BaseRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.stereotype.Repository;

@Repository
public interface LayoutRepo extends BaseRepository,
JpaSpecificationExecutor, 
QuerydslPredicateExecutor {}

4.2服务层写法

在此,向大家推荐一个用于分页查询的Page,PageRequest和Sort,使用起来很方便

引入方式:

import org.springframework.data.domain.*;

接下来,继续介绍服务层写法。

QLayout $ = QLayout.layout;
/**
 * @description: 根据筛选条件查询版面列表,筛选条件后续加版面名称和维护人
 * @author: liu
 * @create: 2022/6/27 15:23
 * @param pageSize 页面条数
 * @param currentPage  当前页面
 * @param parameter   某一筛选查询的字段 
 * @param sortAttribute  排序字段
 * @param orderDirection  排序顺序
 * @return Page
 */
@Override
@Transactional
public Page getAllByCondition(int pageSize, int currentPage, String parameter, String sortAttribute, String orderDirection) {
    BooleanBuilder condition = new BooleanBuilder();
    if (!StringUtils.isEmpty(parameter)) {
        //$.name对应当前实体类对应的这个字段,等同于select * from table where name=parameter
        //(这里contains做的是模糊查询,也可以eq()实现精确查询)
        condition.and($.name.contains(parameter.trim()));
    }
    Sort sortObject = null;
    if (StringUtils.isEmpty(sortAttribute)) {
        sortObject = new Sort(Sort.Direction.DESC, Constant.maintenanceTime);
    } else {
        sortObject = new Sort(Sort.Direction.fromString(orderDirection), sortAttribute);
    }
    PageRequest pageRequest = PageRequest.of(currentPage - 1, pageSize, sortObject);
    return layoutRepo.findAll(condition, pageRequest);
}

4.3控制层写法

        在控制层我们可以使用Page layoutList来接收服务层函数的返回值,并调用getTotalElements()和getTotalPages()获得查到的总条数和总页数,更为方便的是我们也可以使用java的遍历形式对layoutList进行遍历,在此组装需要返回前端的值,整个分页查询就结束了。

5.致谢

        QueryDSL可以搭配实体类中的逻辑外键关联注解,实现更为复杂的inner join、left join和right join,详细用法我还需要进一步整理,感兴趣的大家可以一块交流。

最后,由于本人技术有限,难免出现错误,在此欢迎各位小伙伴们指正并勘误,谢谢大家。

你可能感兴趣的:(SpringBoot框架,java,sql,hibernate)