봄 부팅 (VI) 다음 JPA QueryDSL의 날개 플러그인

이전 글에서, 우리는 사용 JPA 기준 도입 "봄 부트 (3 개) : JPA 히카리 연결 풀링와 ORM 프레임 워크" JPA에가 날개를 소개하는이 문서를, 우리는 항목에 진출 QueryDSL.

1. 소개

모두 단일 테이블 쿼리의 전제에 내장되어 위의 우리는 JPA는 매우 단순화 된 구성 만, 쉽게 의미를 이해하기 위해 어떤 XML 구성 파일없이, 주석을 사용할 필요, 사용이 매우 쉽다는 것을 부인할 수없는 사실이지만, 당신은 단순히 쉽게 완전한 CRUD 작업을 추가, 기본적으로 제공 JPA 방법을 사용할 수 있습니다.

이 동적 쿼리 테이블을 멀티 오는 경우에, 우리는 주석 사용할 수 있지만 JPA 기능을 뻗어 조금 보이는 @Query, 모두이 댓글에서 SQL 또는 HQL의 문자열 연결을 서면으로 문자열의 가독성을하고 바느질이 매우이다 차이는 물론, JPA는 또한 우리가 제공하는 Specification초보자가 시작하는 때, 나쁜 생각, 내 개인, 가독성에서 말하기의 경험을 이용하고, 그것을 할, Predicate그리고 CriteriaBuilder사용은 많은 사람들을 낙담으로 추정되며, SQL의 직접 실행도 테이블을 쿼리 경우 얻을 Object[], 어떤 종류의? 어떤 열 이름? 다음은 우리가 수동으로해야 얻을 직관적없는 Object[]우리의 요구에 대응 Model이 경험은 의심 할 여지없이 매우 나쁘다, 내부 가고 클래스입니다.

이 모든 QueryDSL 태어난 후 결국, QueryDSL SQL 구문은 추가 구성없이, 내 개인적인 경험에서 말하는 것은 대단한 사용, 소개 아름다운 이상 ,, 매우 JPA와 통합, 매우 강한 코드의 가독성과 매우 유사하다 가. 오래 쓰기 SQL로, 기본적으로 그냥 항목의 수준을 달성 할 수있는 샘플 코드를 보면, 말할 수있다.

2. QueryDSL 프로필

QueryDSL 최신 버전은 4.2.1이며, 그룹 Querydsl 구글과 StackOverflow의 두 팀에 의해 지원, 매우 활동적인 오픈 소스 프로젝트, Github에서에 게시 된 현재의 릴리스 버전이 많은 (251)와 같은 버전이 있습니다.

QueryDSL는 SQL과 같은 구조를 정적으로 입력 된 쿼리에서 사용할 수있는 프레임 워크입니다. API는 같은 대신 인라인 문자열로 또는 외부 XML 파일에 쿼리를 작성하는 쿼리와 같은 QueryDSL로 구성 할 수있다.

예를 들어, 간단한 문자열 비교 API를 사용의 장점입니다

  • 코드 완료 IDE

  • 거의 쿼리 구문이 잘못되었습니다

  • 참조 필드 유형 및 속성 안전하게 할 수

  • 더 나은 변화의 도메인 유형을 재구성

3. QueryDSL 실제 사용

3.1 메이븐 의존 소개

리스팅 : 봄 - 부팅-JPA-querydsl / pom.xml 파일
***

<!--QueryDSL支持-->
<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-apt</artifactId>
    <scope>provided</scope>
</dependency>
<!--QueryDSL支持-->
<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-jpa</artifactId>
</dependency>
  • 여기에 버전 번호를 지정하지 않고 된 spring-boot-dependencies프로젝트를 정의했다.

Maven 플러그인 3.2 추가

이 플러그인을 추가하면 프로그램이 자동으로 쿼리 유형을 생성 할 수 있도록 ( "Q"+ 엔티티 이름에 해당로 명명 된 질의 엔티티)입니다.
이에 대한보다 통합 querydsl-APT 종속 플러그인 서비스입니다.

참고 : 사용하는 동안, 프로젝트 (오른쪽 프로젝트 -> 메이븐 -> 업데이트 폴더를) 해결할 수에 대해 상황 발생 쿼리 유형이 자동으로 받는다는 업데이트로 생성 할 수없는 경우.

리스팅 : 봄 - 부팅-JPA-querydsl / pom.xml 파일
***

<plugins>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
    </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>
    </plugin>
</plugins>

3.3 업데이트 및 삭제

JPA에서는 업데이트하고 삭제하는 방법을 사용하기 아주 쉬운 우리에게 제공하고, 우리는 QueryDSL를 업데이트를 사용하고 삭제할 필요가 없지만, 여기 참조를 위해 사용됩니다 :

代码清单: springboot-JPA-querydsl / SRC / 메인 / 자바 / COM / springboot / springbootjpaquerydsl / 서비스 / IMPL / UserServiceImpl.java
***

@Override
public Long update(String id, String nickName) {
    QUserModel userModel = QUserModel.userModel;
    // 更新
    return queryFactory.update(userModel).set(userModel.nickName, nickName).where(userModel.id.eq(id)).execute();
}

@Override
public Long delete(String id) {
    QUserModel userModel = QUserModel.userModel;
    // 删除
    return queryFactory.delete(userModel).where(userModel.id.eq(id)).execute();
}

3.2 쿼리

이 점에서 QueryDSL 쿼리는 연주라고 할 수있는 매우 같은 몇 가지 관련으로, 소비 select()fetch()다음과 사용 문구 :

代码清单: springboot-JPA-querydsl / SRC / 메인 / 자바 / COM / springboot / springbootjpaquerydsl / 서비스 / IMPL / UserServiceImpl.java
***

@Override
public List<String> selectAllNameList() {
    QUserModel userModel = QUserModel.userModel;
    // 查询字段
    return queryFactory.select(userModel.nickName).from(userModel).fetch();
}

@Override
public List<UserModel> selectAllUserModelList() {
    QUserModel userModel = QUserModel.userModel;
    // 查询实体
    return queryFactory.selectFrom(userModel).fetch();
}

@Override
public List<UserDTO> selectAllUserDTOList() {
    QUserModel userModel = QUserModel.userModel;
    QLessonModel lessonModel = QLessonModel.lessonModel;
    // 连表查询实体并将结果封装至DTO
    return queryFactory
            .select(
                    Projections.bean(UserDTO.class, userModel.nickName, userModel.age, lessonModel.startDate, lessonModel.address, lessonModel.name)
            )
            .from(userModel)
            .leftJoin(lessonModel)
            .on(userModel.id.eq(lessonModel.userId))
            .fetch();
}

@Override
public List<String> selectDistinctNameList() {
    QUserModel userModel = QUserModel.userModel;
    // 去重查询
    return queryFactory.selectDistinct(userModel.nickName).from(userModel).fetch();
}

@Override
public UserModel selectFirstUser() {
    QUserModel userModel = QUserModel.userModel;
    // 查询首个实体
    return queryFactory.selectFrom(userModel).fetchFirst();
}

@Override
public UserModel selectUser(String id) {
    QUserModel userModel = QUserModel.userModel;
    // 查询单个实体,如果结果有多个,会抛`NonUniqueResultException`。
    return queryFactory.selectFrom(userModel).fetchOne();
}

3.4 복잡한 쿼리 작업

간단한 쿼리 위, 실제로 우리는 아래의 예를 사용하여, 같은 서브 쿼리, 쿼리, 멀티 테이블도 확인 멀티 기준으로 매우 복잡한 작업을 발생할 수 :

代码清单: springboot-JPA-querydsl / SRC / 메인 / 자바 / COM / springboot / springbootjpaquerydsl / 서비스 / IMPL / LessonServiceImpl.java
***

@Service
public class LessonServiceImpl implements LessonService {

    @Autowired
    JPAQueryFactory queryFactory;

    @Override
    public List<LessonModel> findLessonList(String name, Date startDate, String address, String userId) throws ParseException {
        QLessonModel lessonModel = QLessonModel.lessonModel;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        // 多条件查询示例
        return queryFactory.selectFrom(lessonModel)
                .where(
                        lessonModel.name.like("%" + name + "%")
                        .and(lessonModel.address.contains(address))
                        .and(lessonModel.userId.eq(userId))
                        .and(lessonModel.startDate.between(simpleDateFormat.parse("2018-12-31 00:00:00"), new Date()))
                )
                .fetch();
    }

    @Override
    public List<LessonModel> findLessonDynaList(String name, Date startDate, String address, String userId) throws ParseException {
        QLessonModel lessonModel = QLessonModel.lessonModel;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

        // 动态查询示例
        BooleanBuilder builder = new BooleanBuilder();

        if (!StringUtils.isEmpty(name)){
            builder.and(lessonModel.name.like("%" + name + "%"));
        }

        if (startDate != null) {
            builder.and(lessonModel.startDate.between(simpleDateFormat.parse("2018-12-31 00:00:00"), new Date()));
        }

        if (!StringUtils.isEmpty(address)) {
            builder.and(lessonModel.address.contains(address));
        }

        if (!StringUtils.isEmpty(userId)) {
            builder.and(lessonModel.userId.eq(userId));
        }

        return queryFactory.selectFrom(lessonModel).where(builder).fetch();
    }

    @Override
    public List<LessonModel> findLessonSubqueryList(String name, String address) {
        QLessonModel lessonModel = QLessonModel.lessonModel;
        // 子查询示例,并无实际意义
        return queryFactory.selectFrom(lessonModel)
                .where(lessonModel.name.in(
                        JPAExpressions
                                .select(lessonModel.name)
                                .from(lessonModel)
                                .where(lessonModel.address.eq(address))
                ))
                .fetch();
    }
}

3.5 MySQL의 집합 함수

그들은 당황 할 필요는 없다 집계 함수의 QueryDSL를 제공하지 않는 경우 QueryDSL는, 몇 가지 일반적인 MySQL의 집계 기능을 구축하고, QueryDSL이 우리에게 제공 Expressions이 클래스, 우리는 수동 접합, 다음의 예와 같이,이 클래스를 사용할 수 있습니다 :

代码清单: springboot-JPA-querydsl / SRC / 메인 / 자바 / COM / springboot / springbootjpaquerydsl / 서비스 / IMPL / UserServiceImpl.java
***

@Override
public String mysqlFuncDemo(String id, String nickName, int age) {

    QUserModel userModel = QUserModel.userModel;

    // Mysql 聚合函数示例

    // 聚合函数-avg()
    Double averageAge = queryFactory.select(userModel.age.avg()).from(userModel).fetchOne();

    // 聚合函数-sum()
    Integer sumAge = queryFactory.select(userModel.age.sum()).from(userModel).fetchOne();

    // 聚合函数-concat()
    String concat = queryFactory.select(userModel.nickName.concat(nickName)).from(userModel).fetchOne();

    // 聚合函数-contains()
    Boolean contains = queryFactory.select(userModel.nickName.contains(nickName)).from(userModel).where(userModel.id.eq(id)).fetchOne();

    // 聚合函数-DATE_FORMAT()
    String date = queryFactory.select(Expressions.stringTemplate("DATE_FORMAT({0},'%Y-%m-%d')", userModel.createDate)).from(userModel).fetchOne();

    return null;
}

4. 요약

소개가 직접 읽기 SQL 느낌이 아닌,이는 일을하지 않았 최대 절전 모드를 제공한다 SQL의 OOM을 사용하는 아이디어입니다, 당신의 독자가 위의 예를 읽을 모르는, 여기 끝으로 QueryDSL하기 간단하고 사용하기 쉬운 오히려 완벽한 솔루션, 운영,하지만 SQL을 작성하지 않고, 우리가 실제로 작동하거나 객체 클래스.

5. 샘플 코드

코드 -Github 샘플

코드 -Gitee 샘플

6. 참고 문헌

"QueryDSL 공식 문서"

추천

출처www.cnblogs.com/babycomeon/p/11605809.html