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 操作數據表做複雜查詢是非常棒的。具體細節到官網查看吧

關注一個個人微信公衆號吧!感謝!
在這裏插入圖片描述

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