Springboot之QueryDSL增强JPA操作

Springboot使用queryDSL

一、简介

Querydsl 是一个类型安全的 Java 查询框架,支持 JPA, JDO, JDBC, Lucene, Hibernate Search 等标准。类型安全(Type safety)和一致性(Consistency)是它设计的两大准则。在 Spring Boot 中可以很好的弥补 JPA 的不灵活,实现更强大的逻辑。

JPA操作多表操作的时候,很麻烦,我们也可以建关联关系,但是需要维护一对关系,序列化的问题,JPA的单表操作也很麻烦,不然就得写SQL语句,一点都不灵活。非常怀念MyBatis-plus,所幸找到了QueryDSL这个Java框架,大大的简化了JPA查询的复杂度。

下面就是一个操作JPA单表复杂查询

/**
 * 组装条件查询
 *
 * @param companyReq
 * @return
 */
private Specification selectCompanyCondition(CompanyReq companyReq) {
    return new Specification() {
        @Override
        public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {
            List<Predicate> predicates = Lists.newArrayList();
            // 英文简称
            if (!StringUtils.isEmpty(companyReq.getCompanyCode())) {
                predicates.add(criteriaBuilder.equal(root.get("companyCode"), companyReq.getCompanyCode()));
            }
            // 企业域名
            if (!StringUtils.isEmpty(companyReq.getCompanyDNS())) {
                predicates.add(criteriaBuilder.equal(root.get("companyDNS"), companyReq.getCompanyDNS()));
            }
            // 英文全称
            if (!StringUtils.isEmpty(companyReq.getCompanyFullCode())) {
                predicates.add(criteriaBuilder.equal(root.get("companyFullCode"), companyReq.getCompanyFullCode()));
            }
            // 企业简称
            if (!StringUtils.isEmpty(companyReq.getCompanyName())) {
                predicates.add(criteriaBuilder.like(root.get("companyName"), "%" + companyReq.getCompanyName() + "%"));
            }
            // 注册时间 时间段之内
            if ((companyReq.getCreateEndTime() != null) && (companyReq.getCreateStartTime() != null)) {
                predicates.add(criteriaBuilder.between(root.get("createTime"), companyReq.getCreateStartTime(), companyReq.getCreateEndTime()));
            }
            // 按照创建时间排序 默认为 不传该字段 或者 rankType = true  为  降序
            if (companyReq.getRankType() == null || companyReq.getRankType()) {
                query.orderBy(criteriaBuilder.desc(root.get("createTime")));
            } else {
                query.orderBy(criteriaBuilder.asc(root.get("createTime")));
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
        }
    };
}

并且在不是很想加关联关系,但是想做关联查询。就很无奈了,我并没有找到好的方法区处理。QueryDSL就可以很好地处理。下面开始介绍!

二、添加依赖

<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-apt</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-jpa</artifactId>
</dependency>

三、添加maven插件

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <!--  插件失败:将{JAVA_HOME}/lib/tools.jar 复制到 jre/lib 目录下  -->
            <!--  插件如果还是飘红,无所谓,无视就可以  -->
            <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</outputDirectory>
                        <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

四、添加QueryDSL的配置类

import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.persistence.EntityManager;

/**
 * @author 墨龙吟
 * @version 1.0.0
 * @ClassName QueryDSLConfig.java
 * @Email [email protected]
 * @Description TODO
 * @createTime 2019年08月27日 - 19:52
 */
@Configuration
public class QueryDSLConfig {

    @Autowired
    private EntityManager entityManager;

    @Bean
    public JPAQueryFactory getQueryFactory() {
        return new JPAQueryFactory(entityManager);
    }

}

五、实例使用

在操作Service类中注入JPAQueryFactory

@Autowired
private JPAQueryFactory queryFactory;

然后就可以操作了数据表了。

where和orderBy使用:

@Override
public List<FileEntity> getAll() {
    QFileEntity qFileEntity = QFileEntity.fileEntity;
    return queryFactory.selectFrom(qFileEntity)
        .where(qFileEntity.canView.eq(true))
        .orderBy(qFileEntity.createTime.desc())
        .fetch();
}

多表联查,返回指定的字段

@Override
public List<FileVO> getFileList() {
    QFileEntity qFileEntity = QFileEntity.fileEntity;
    QUserEntity qUserEntity = QUserEntity.userEntity;
    List<FileVO> result = queryFactory
        .select(Projections.bean(
            FileVO.class,
            qFileEntity.fileUrl,
            qFileEntity.fileName,
            qFileEntity.fileId,
            qFileEntity.updateTime,
            qFileEntity.createTime,
            qFileEntity.userId,
            qFileEntity.brief,
            qUserEntity.userName,
            qFileEntity.isDefault
        ))
        .from(qFileEntity)
        .leftJoin(qUserEntity)
        .on(qFileEntity.userId.eq(qUserEntity.userId))
        .where(qFileEntity.canView.eq(true))
        .orderBy(qFileEntity.createTime.desc())
        .fetch();
    return result;
}

直接返回实体类

@Override
public List<UserEntity> checkUserInfo(String username) {
    QUserEntity qUserEntity = QUserEntity.userEntity;
    return queryFactory
        .selectFrom(qUserEntity)
        .where(qUserEntity.userName.eq(username).and(qUserEntity.canView.eq(true)))
        .fetch();
}

六、总结

QueryDSL 操作数据表做复杂查询是非常棒的。具体细节到官网查看吧

关注一个个人微信公众号吧!感谢!
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章