美文网首页
QueryDsl使用

QueryDsl使用

作者: 伟_4649 | 来源:发表于2020-03-17 16:22 被阅读0次
    使用jpa的一些困扰
    • 一对多,多对一,多对多的关系要不要建立?
    • 返回类型Object[]数组,至于每一个下标对应哪个字段,没法直观的看到,例如object[11]是什么类型?字段名是什么?这个就无法直观得知.
    • jpql/native sql中复杂的关系导致不可维护,每一个接手的人都要研究sql半天
    • 该种动态拼接条件方法导致类似的代码会大量重复,所以IDEA打开的时候黄了半边天
    • 该查询为分页查询,这样写的话,还要再copy一个count查询才能拿到总数,无疑又是代码重复
    • JPA这种框架目的就是少些原生sql语句,大量这样的操作的话,还不如使用dbUtil这样的工具类查询
    QueryDsl简介

    QueryDSL仅仅是一个通用的查询框架,专注于通过Java API构建类型安全的SQL查询。
    Querydsl可以通过一组通用的查询API为用户构建出适合不同类型ORM框架或者是SQL的查询语句,也就是说QueryDSL是基于各种ORM框架以及SQL之上的一个通用的查询框架。
    借助QueryDSL可以在任何支持的ORM框架或者SQL平台上以一种通用的API方式来构建查询。目前QueryDSL支持的平台包括JPA,JDO,SQL,Java Collections,RDF,Lucene,Hibernate Search。
    官网地址 : 点击进入

    配置到项目

    pom.xml 引入依赖 加入插件,用于生成查询实例Q类

    <dependencies>
            <dependency>
                <groupId>com.querydsl</groupId>
                <artifactId>querydsl-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>com.querydsl</groupId>
                <artifactId>querydsl-apt</artifactId>
            </dependency>
    </dependencies>
    <plugins>
            <plugin> <!--因为QueryDsl是类型安全的,所以还需要加上Maven APT plugin,使用 APT 自动生成Q类:-->
                    <groupId>com.mysema.maven</groupId>
                    <artifactId>apt-maven-plugin</artifactId>
                    <version>1.1.3</version>
                    <executions>
                        <execution>
                            <phase>generate-sources</phase>
                            <goals>
                                <goal>process</goal>
                            </goals>
                            <configuration>
                                <outputDirectory>target/generated-sources/java</outputDirectory>
                                <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
    </plugins>
    

    实体Bean配置了@Entity被检测到之后,就会在target的子目录中自动生成一个Q+实体名称的类,这个类对我们使用QueryDSL非常重要,正是因为它,我们才使得QueryDSL能够构建类型安全的查询。

    修改代码
    • 在启动类中添加如下代码
        /**
         * 让Spring管理JPAQueryFactory
         */
        @Bean
        public JPAQueryFactory jpaQueryFactory(EntityManager entityManager){
            return new JPAQueryFactory(entityManager);
        }
    
    • 修改Repository类
    @Repository
    public interface CustomerRepository extends JpaRepository<Customer, String>, QuerydslPredicateExecutor<Customer>
    
    QueryDsl大于等于,小于等于

    大于等于 :goe,小于等于:loe

    predicate = StringUtils.isEmpty(param.getParam().get("start")) ? predicate : ExpressionUtils.and(predicate, qMonthcheckplan.start.goe(DateUtils.str2day(param.getParam().get("start").toString())));
    predicate = StringUtils.isEmpty(param.getParam().get("end")) ? predicate : ExpressionUtils.and(predicate, qMonthcheckplan.end.loe(DateUtils.str2day(param.getParam().get("end").toString())));
    
    查询并分页
    • 简单分页
    Pageable pageable = PageRequest.of(query.getPage() - 1, query.getSize());
    Predicate predicate = customer.isNotNull().or(customer.isNull());
    predicate = query.getBirthdayBegin() == null ? predicate : ExpressionUtils.and(predicate, customer.birthday.goe(query.getBirthdayBegin()));
    predicate = query.getBirthdayEnd() == null ? predicate : ExpressionUtils.and(predicate, customer.birthday.loe(query.getBirthdayEnd()));
    Page<Customer> pageData = customerRepository.findAll(predicate, pageable);
    List<CustomerVO> customers = new ArrayList<>();
    pageData.getContent().forEach(x -> {
        CustomerVO customerVO = CustomerVO.builder().build();
        BeanUtils.copyProperties(x, customerVO);
        customers.add(customerVO);
    });
    return Result.ok(customers, pageData.getTotalElements());
    
    • 条件分页
      QCustomer QCustomerOrder:是编译出来的实体
      jpaQuery :根据条件查询出来的集合
      customers :根据前台传来的进行分页操作
      .fetch():相当于.get() 可看出返回类型
    QCustomer customer = QCustomer.customer;
    QCustomerOrder order = QCustomerOrder.customerOrder;
    
    Pageable pageable = PageRequest.of(query.getPage() - 1, query.getSize());
    
    //组合搜索客户的条件,初始化组装条件(类似where 1=1)
    Predicate predicate = customer.isNotNull().or(customer.isNull());
    predicate = StrUtil.isBlank(query.getCustomerName()) ? predicate : ExpressionUtils.and(predicate, customer.name.like(FnaUtils.parseLike(query.getCustomerName())));
    predicate = StrUtil.isBlank(query.getGender()) ? predicate : ExpressionUtils.and(predicate, customer.gender.eq(query.getGender()));
    predicate = query.getBirthdayBegin() == null ? predicate : ExpressionUtils.and(predicate, customer.birthday.goe(query.getBirthdayBegin()));
    predicate = query.getBirthdayEnd() == null ? predicate : ExpressionUtils.and(predicate, customer.birthday.loe(query.getBirthdayEnd()));
    predicate = StrUtil.isBlank(query.getIdType()) ? predicate : ExpressionUtils.and(predicate, customer.idType.eq(query.getIdType()));
    predicate = StrUtil.isBlank(query.getIdNo()) ? predicate : ExpressionUtils.and(predicate, customer.idNo.like(FnaUtils.parseLike(query.getIdNo())));
    
    //组合搜索客户订单的条件,初始化组装条件(类似where 1=1)
    Predicate predicate2 = order.isNotNull().or(order.isNull());
    predicate2 = StrUtil.isBlank(query.getOrderNo()) ? predicate2 : ExpressionUtils.and(predicate2, order.orderNo.like(FnaUtils.parseLike(query.getOrderNo())));
    predicate2 = StrUtil.isBlank(query.getAddress()) ? predicate2 : ExpressionUtils.and(predicate2, order.address.like(FnaUtils.parseLike(query.getAddress())));
    
    JPAQuery<Customer> jpaQuery = jpaQueryFactory.selectFrom(customer).where(predicate);
    if (StrUtil.isNotBlank(query.getOrderNo()) || StrUtil.isNotBlank(query.getAddress())) {
        jpaQuery.where(customer.customerId.in(
                jpaQueryFactory.select(order.customerId).from(order).where(predicate2))
        );
    }
    List<CustomerVO> customers = jpaQuery.offset(pageable.getOffset()).limit(pageable.getPageSize()).fetch().stream().map(x -> {
        CustomerVO customerVO = CustomerVO.builder().build();
        BeanUtils.copyProperties(x, customerVO);
        return customerVO;
    }).collect(Collectors.toList());
    long count = jpaQuery.fetchCount();
    return Result.ok(customers, count);
    

    相关文章

      网友评论

          本文标题:QueryDsl使用

          本文链接:https://www.haomeiwen.com/subject/vkwtyhtx.html