본문 바로가기
SpringBoot

Querydsl 배워서 사용하기

by moonchance 2024. 1. 11.

머리말

Querydsl은 정적으로 유형이 지정된 SQL과 유사한 쿼리를 생성할 수 있는 프레임워크입니다. 쿼리를 인라인 문자열로 작성하거나 XML 파일로 외부화하는 대신 Querydsl과 같은 유연한 API를 통해 생성할 수 있습니다.

간단한 문자열과 비교하여 유창한 API를 사용하면 다음과 같은 이점이 있습니다.

  • IDE에서 코드 완성
  • 거의 없음 구문적으로 잘못된 쿼리는 허용되지 않음
  • 도메인 유형 및 속성을 안전하게 참조할 수 있습니다.
  • 도메인 유형의 변경 사항을 리팩토링하는 데 더 잘 적응합니다.

1. 소개

1.1. 배경

Querydsl은 HQL 쿼리를 형식이 안전한 방식으로 유지해야 할 필요성에서 탄생했습니다. HQL 쿼리의 증분 구성에는 문자열 연결이 필요하므로 코드를 읽기가 어렵습니다. 일반 문자열을 통한 도메인 유형 및 속성에 대한 안전하지 않은 참조는 문자열 기반 HQL 구성의 또 다른 문제였습니다.

변화하는 도메인 모델 유형 안전성은 소프트웨어 개발에 큰 이점을 제공합니다. 도메인 변경 사항은 쿼리에 직접 반영되며 쿼리 구성 시 자동 완성을 통해 쿼리 구성이 더 빠르고 안전해집니다.

Hibernate용 HQL은 Querydsl의 첫 번째 대상 언어였지만 현재는 JPA, JDO, JDBC, Lucene, Hibernate Search, MongoDB, Collections 및 RDFBean을 백엔드로 지원합니다.

Java의 데이터베이스 액세스가 처음이라면 https://www.marcobehler.com/guides/a-guide-to-accessing-databases-in-java에 다양한 부분, 부분, 옵션 및 쇼에 대한 좋은 개요가 포함되어 있습니다. QueryDSL이 딱 들어맞는 곳입니다.

1.2. 원칙

유형 안전성은 Querydsl의 핵심 원칙입니다. 쿼리는 도메인 유형의 속성을 반영하는 생성된 쿼리 유형을 기반으로 구성됩니다. 또한 함수/메서드 호출은 완전히 유형이 안전한 방식으로 구성됩니다.

일관성은 또 다른 중요한 원칙입니다. 쿼리 경로와 작업은 모든 구현에서 동일하며 쿼리 인터페이스에도 공통 기본 인터페이스가 있습니다.

Querydsl 쿼리 및 표현식 유형의 표현성에 대한 인상을 얻으려면 javadocs로 이동하여 com.querydsl.core.Query탐색 com.querydsl.core.Fetchable  com.querydsl.core.types.Expression.

2. 튜토리얼

일반적인 시작 가이드 대신 Querydsl의 주요 백엔드에 대한 통합 가이드를 제공합니다.

2.1. JPA 쿼리 중

Querydsl은 지속형 도메인 모델 데이터를 기반으로 쿼리하기 위한 일반적인 정적인 형식의 구문을 정의합니다. JDO와 JPA는 Querydsl의 주요 통합 기술입니다. 이 가이드에서는 JPA와 함께 Querydsl을 사용하는 방법을 설명합니다.

JPA용 Querydsl은 JPQL 및 기준 쿼리에 대한 대안입니다. 이는 기준 쿼리의 동적 특성과 JPQL의 표현력 및 모든 기능을 완전히 유형이 안전한 방식으로 결합합니다.

2.1.1. 메이븐 통합

Maven 프로젝트에 다음 종속성을 추가합니다.

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-apt </artifactId> 
  <version> ${querydsl.version} </version> 
  <scope> 제공 </scope> 
</dependent>

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-jpa </artifactId> 
  <version> ${querydsl.version} </version> 
</dependent>

이제 Maven APT 플러그인을 구성합니다.

<프로젝트> 
  <빌드> 
  <플러그인>
    ...
    <plugin> 
      <groupId> com.mysema.maven </groupId> 
      <artifactId> apt-maven-plugin </artifactId> 
      <version> 1.1.3 </version> 
      <executions> 
        <execution> 
          <goals> 
            <goal> 프로세스 </goal> 
          </goals> 
          <configuration> 
            <outputDirectory> target/generated-sources/java </outputDirectory> 
            <processor> com.querydsl.apt.jpa.JPAAnnotationProcessor </processor> 
          </configuration> 
        </execution> 
      < /실행> </ 
    플러그인 >
    ...
  </플러그인> 
  </build> 
</project>

JPAAnnotationProcessor는 javax.persistence.Entity 주석이 달린 도메인 유형을 찾고 이에 대한 쿼리 유형을 생성합니다.

도메인 유형에서 Hibernate 주석을 사용하는 경우 대신 APT 프로세서를 사용해야 합니다 com.querydsl.apt.hibernate.HibernateAnnotationProcessor .

새로 설치를 실행하면 쿼리 유형이 target/generated-sources/java에 생성됩니다.

Eclipse를 사용하는 경우 mvn eclipse:eclipse를 실행하여 target/generated-sources/java를 소스 폴더로 포함하도록 Eclipse 프로젝트를 업데이트하십시오.

이제 JPA 쿼리 인스턴스와 쿼리 도메인 모델의 인스턴스를 구성할 수 있습니다.

2.1.2. 개미 통합

full-deps 번들의 jar 파일을 클래스 경로에 배치하고 Querydsl 코드 생성을 위해 다음 작업을 사용합니다.

    <!-- APT 기반 코드 생성 --> 
    <javac  srcdir = "${src}"  classpathref = "cp" > 
      <compilerarg  value = "-proc:only" /> 
      <compilerarg  value = "-processor" /> 
      < compilerarg  값 = "com.querydsl.apt.jpa.JPAAnnotationProcessor" /> 
      <compilerarg  값 = "-s" /> 
      <compilerarg  값 = "${generated}" /> 
    </javac>

    <!-- 컴파일 --> 
    <javac  classpathref = "cp"  destdir = "${build}" > 
      <src  경로 = "${src}" /> 
      <src  경로 = "${generated}" /> 
    </ javac>

src를 생성된 소스용 폴더로 생성된 기본 소스 폴더로 바꾸고 대상 폴더로 빌드합니다 .

2.1.3. Roo에서 Querydsl JPA 사용

Spring Roo와 함께 Querydsl JPA를 사용하는 경우 주석이 달린 클래스 대신 핸들 및 주석이 달린 클래스 com.querydsl.apt.jpa.JPAAnnotationProcessor 로 바꿀 수 있습니다 . com.querydsl.apt.roo.RooAnnotationProcessor@RooJpaEntity@RooJpaActiveRecord@Entity

APT 기반 코드 생성은 AspectJ IDT에서 제대로 작동하지 않습니다.

2.1.4. hbm.xml 파일에서 모델 생성

XML 기반 구성으로 Hibernate를 사용하는 경우 XML 메타데이터를 사용하여 Querydsl 모델을 생성할 수 있습니다.

com.querydsl.jpa.codegen.HibernateDomainExporter이에 대한 기능을 제공합니다:

HibernateDomainExporter 내보내기 = new HibernateDomainExporter(
   "Q" ,                      // 이름 접두어 
  new File( "target/gen3" ), // 대상 폴더 
  구성);          // org.hibernate.cfg.Configuration의 인스턴스

수출업자.수출();

HibernateDomainExporter는 속성 유형이 리플렉션을 통해 해결되므로 도메인 유형이 표시되는 클래스 경로 내에서 실행되어야 합니다.

모든 JPA 주석은 무시되지만 @QueryInit 및 @QueryType과 같은 Querydsl 주석은 고려됩니다.

2.1.5. 쿼리 유형 사용

Querydsl로 쿼리를 생성하려면 변수와 쿼리 구현을 인스턴스화해야 합니다. 변수부터 시작하겠습니다.

프로젝트에 다음과 같은 도메인 유형이 있다고 가정해 보겠습니다.

@Entity
 공용  클래스 Customer {
     private String firstName;
    개인 문자열 성;

    공개 문자열 getFirstName() {
         return firstName;
    }

    공개 문자열 getLastName() {
         return lastName;
    }

    공공  무효 setFirstName(문자열 fn) {
        이름 = fn;
    }

    공공  무효 setLastName(문자열 ln) {
        성 = ln;
    }
}

Querydsl은 Customer와 동일한 패키지에 QCustomer라는 간단한 이름을 가진 쿼리 유형을 생성합니다. QCustomer는 Customer 유형을 대표하는 Querydsl 쿼리에서 정적으로 유형이 지정된 변수로 사용될 수 있습니다.

QCustomer에는 정적 필드로 액세스할 수 있는 기본 인스턴스 변수가 있습니다.

QCustomer 고객 = QCustomer.customer;

또는 다음과 같이 고유한 Customer 변수를 정의할 수 있습니다.

QCustomer 고객 = new QCustomer( "myCustomer" );

2.1.6. 쿼리 중

Querydsl JPA 모듈은 JPA와 Hibernate API를 모두 지원합니다.

JPA API를 사용하려면 JPAQuery다음과 같이 쿼리에 인스턴스를 사용합니다.

// 여기서 EntityManager는 JPA EntityManager입니다. 
JPAQuery<?> query = new JPAQuery<Void>(entityManager);

대신 Hibernate API를 사용하는 경우 HibernateQuery다음과 같이 인스턴스화할 수 있습니다.

// 세션은 Hibernate 세션입니다. 
HibernateQuery<?> query = new HibernateQuery<Void>(session);

둘 다 JPAQuery인터페이스 를 HibernateQuery구현합니다 JPQLQuery.

이 장의 예에서는 쿼리가 인스턴스를 통해 생성됩니다 JPAQueryFactory. JPAQueryFactory인스턴스를 얻으려면 선호되는 옵션이어야 합니다 JPAQuery.

Hibernate API의 경우 HibernateQueryFactory사용할 수 있습니다

이름이 Bob인 고객을 검색하려면 다음과 같은 쿼리를 구성합니다.

QCustomer 고객 = QCustomer.customer;
고객 bob = queryFactory.selectFrom(고객)
  .where(customer.firstName.eq( "밥" ))
  .fetchOne();

selectFrom 호출은 쿼리 소스와 프로젝션을 정의하고, where 부분은 필터를 정의하고 fetchOne은 Querydsl에 단일 요소를 반환하도록 지시합니다. 쉽지요?

여러 소스가 포함된 쿼리를 만들려면 다음과 같은 쿼리를 사용하세요.

QCustomer 고객 = QCustomer.customer;
Q회사 회사 = QCompany.company;
query.from(고객, 회사);

여러 필터를 사용하려면 다음과 같이 사용하십시오.

queryFactory.selectFrom(고객)
    .where(customer.firstName.eq( "밥" ), customer.lastName.eq( "윌슨" ));

아니면 이렇게

queryFactory.selectFrom(고객)
    .where(customer.firstName.eq( "Bob" ).and(customer.lastName.eq( "Wilson" )));

기본 JPQL 형식에서 쿼리는 다음과 같이 작성됩니다.

고객에서 고객을 고객으로 선택
여기서 customer.firstName = "Bob"이고 customer.lastName = "Wilson"입니다.

"or"를 통해 필터를 결합하려면 다음 패턴을 사용하십시오.

queryFactory.selectFrom(고객)
    .where(customer.firstName.eq( "Bob" ).or(customer.lastName.eq( "Wilson" )));

2.1.7. 조인 사용

Querydsl은 JPQL에서 내부 조인, 조인, 왼쪽 조인 및 오른쪽 조인과 같은 조인 변형을 지원합니다. 조인 사용은 형식이 안전하며 다음 패턴을 따릅니다.

QCat 고양이 = QCat.cat;
QCat 메이트 = new QCat( "메이트" );
QCat 새끼 고양이 = new QCat( "새끼 고양이" );
queryFactory.selectFrom(cat)
    .innerJoin(cat.mate, 메이트)
    .leftJoin(cat.kittens, 새끼 고양이)
    .술책();

쿼리의 기본 JPQL 버전은 다음과 같습니다.

Cat에서 고양이를 고양이로 선택
내부 조인 cat.mate를 메이트로
왼쪽 외부 조인 cat.kittens를 새끼 고양이로 사용

다른 예시

queryFactory.selectFrom(cat)
    .leftJoin(cat.kittens, 새끼 고양이)
    .on(kitten.bodyWeight.gt( 10.0 ))
    .술책();

다음 JPQL 버전 사용

Cat에서 고양이를 고양이로 선택
cat.kittens에 새끼고양이로 가입하세요
새끼고양이.bodyWeight > 10.0

2.1.8. 일반적인 사용법

다음과 같이 JPQLQuery 인터페이스의 계단식 메소드를 사용하십시오.

select: 쿼리의 투영을 설정합니다. (쿼리 팩토리를 통해 생성된 경우 필요하지 않음)

from: 여기에 쿼리 소스를 추가합니다.

innerJoin, Join, leftJoin, rightJoin, on: 이러한 구성을 사용하여 조인 요소를 추가합니다. 조인 방법의 경우 첫 번째 인수는 조인 소스이고 두 번째 인수는 대상(별칭)입니다.

여기서: 쉼표로 구분된 가변 인수 형식 또는 and 연산자를 통해 계단식으로 연결된 쿼리 필터를 추가합니다.

groupBy: varargs 형식의 인수별로 그룹을 추가합니다.

가지고: "그룹화 기준" 그룹화의 필터를 조건자 표현식의 varags 배열로 추가합니다.

orderBy: 결과의 순서를 순서 표현식의 varargs 배열로 추가합니다. OrderSpecifier 인스턴스에 액세스하려면 숫자, 문자열 및 기타 유사한 표현식에 asc() 및 desc()를 사용하십시오.

제한, 오프셋, 제한: 결과의 페이징을 설정합니다. 최대 결과에 대한 제한, 행 건너뛰기에 대한 오프셋 및 한 번의 호출로 둘 다를 정의하기 위한 제한.

2.1.9. 주문

순서를 선언하는 구문은 다음과 같습니다.

QCustomer 고객 = QCustomer.customer;
queryFactory.selectFrom(고객)
    .orderBy(고객.lastName.asc(), 고객.firstName.desc())
    .술책();

이는 다음 기본 JPQL과 동일합니다.

고객에서 고객을 고객으로 선택
customer.lastName asc, customer.firstName desc로 주문

2.1.10. 그룹화

그룹핑은 다음과 같은 형태로 할 수 있습니다.

queryFactory.select(고객.라스트이름).from(고객)
    .groupBy(고객.성명)
    .술책();

이는 다음 기본 JPQL과 동일합니다.

고객.성명을 선택하세요.
고객으로부터 고객으로
고객.성명별 그룹

2.1.11. 조항 삭제

Querydsl JPA의 삭제 절은 간단한 삭제 위치 실행 형식을 따릅니다. 여기 몇 가지 예가 있어요.

QCustomer 고객 = QCustomer.customer;
// 모든 고객 삭제
queryFactory.delete(고객).execute();
// 레벨 3 미만의 모든 고객 삭제 
queryFactory.delete(customer).where(customer.level.lt( 3 )).execute();

where 호출은 선택 사항이며 실행 호출은 삭제를 수행하고 삭제된 항목의 양을 반환합니다.

JPA의 DML 절은 JPA 수준 계단식 규칙을 고려하지 않으며 세분화된 두 번째 수준 캐시 상호 작용을 제공하지 않습니다.

2.1.12. 조항 업데이트

Querydsl JPA의 업데이트 절은 간단한 업데이트 설정/위치 실행 형식을 따릅니다. 여기 몇 가지 예가 있어요.

QCustomer 고객 = QCustomer.customer;
// Bob이라는 고객의 이름을 Bobby로 바꿉니다. 
queryFactory.update(customer).where(customer.name.eq( "Bob" ))
    .set(고객.이름, "바비" )
    .실행하다();

집합 호출은 SQL 업데이트 스타일로 속성 업데이트를 정의하고 실행 호출은 업데이트를 수행하고 업데이트된 엔터티의 양을 반환합니다.

JPA의 DML 절은 JPA 수준 계단식 규칙을 고려하지 않으며 세분화된 두 번째 수준 캐시 상호 작용을 제공하지 않습니다.

2.1.13. 하위 쿼리

하위 쿼리를 생성하려면 정적 팩토리 메소드를 사용하고 JPAExpressionsfrom, where 등을 통해 쿼리 매개변수를 정의합니다.

QDepartment 부서 = QDepartment.department;
QDepartment d = new QDepartment( "d" );
queryFactory.selectFrom(부서)
    .where(department.size.eq(
        JPAExpressions.select(d.size.max()).from(d)))
     .술책();

다른 예시

QEmployee 직원 = QEmployee.employee;
QEmployee e = new QEmployee( "e" );
queryFactory.selectFrom(직원)
    .where(employee.weeklyhours.gt(
        JPAExpressions.select(e.weeklyhours.avg())
            .from(employee.department.employees, e)
            .where(e.manager.eq(employee.manager))))
    .술책();

2.1.14. 원래 쿼리 노출

쿼리를 실행하기 전에 원래 쿼리를 조정해야 하는 경우 다음과 같이 노출할 수 있습니다.

쿼리 jpaQuery = queryFactory.selectFrom(employee).createQuery();
// ...
결과 나열 = jpaQuery.getResultList();

2.1.15. JPA 쿼리에서 기본 SQL 사용

Querydsl은 JPASQLQuery 클래스를 통해 JPA의 기본 SQL을 지원합니다.

이를 사용하려면 SQL 스키마에 대한 Querydsl 쿼리 유형을 생성해야 합니다. 예를 들어 다음 Maven 구성을 사용하여 이 작업을 수행할 수 있습니다.

<프로젝트> 
  <빌드> 
    <플러그인>
      ...
      <plugin> 
        <groupId> com.querydsl </groupId> 
        <artifactId> querydsl-maven-plugin </artifactId> 
        <version> ${querydsl.version} </version> 
        <executions> 
          <execution> 
            <goals> 
              <goal> 내보내기 </goal> 
            </goals> 
          </execution> 
        </executions> 
        <configuration> 
          <jdbcDriver> org.apache.derby.jdbc.EmbeddedDriver </jdbcDriver> 
          <jdbcUrl> jdbc:derby:target/demoDB;create=true </jdbcUrl> 
          <packageName> com.mycompany.mydomain </packageName> 
          <targetFolder> ${project.basedir}/target/generated-sources/java </targetFolder> 
        </configuration> <종속성> < 
        종속성 
          > 
            <groupId> org.apache.derby </groupId> 
            <artifactId> 더비 </artifactId> 
            <version> ${derby.version} </version> 
          </dependent> 
        </dependent> 
      </plugin>
      ...
    </플러그인> 
  </build> 
</project>

쿼리 유형이 선택한 위치에 성공적으로 생성되면 쿼리에 사용할 수 있습니다.

단일 열 쿼리:

// 직렬화 템플릿 
SQLTemplates template = new DerbyTemplates();
// 쿼리 유형(SQL의 경우 S*, 도메인 유형의 경우 Q*) 
SAnimal cat = new SAnimal( "cat" );
SAnimal 메이트 = new SAnimal( "메이트" );
QCat catEntity = QCat.cat;

JPASQLQuery<?> 쿼리 = new JPASQLQuery<Void>(entityManager, 템플릿);
List<String> names = query.select(cat.name).from(cat).fetch();

쿼리에 엔터티(예: QCat)와 테이블(예: SAnimal) 참조를 혼합하는 경우 동일한 변수 이름을 사용하는지 확인해야 합니다. SAnimal.animal에는 변수 이름 "animal"이 있으므로 새 인스턴스(new SAnimal("cat"))가 대신 사용되었습니다.

대체 패턴은 다음과 같습니다.

QCat catEntity = QCat.cat;
SAnimal cat = new SAnimal(catEntity.getMetadata().getName());

여러 열 쿼리:

query = new JPASQLQuery<Void>(entityManager, 템플릿);
List<Tuple> 행 = query.select(cat.id, cat.name).from(cat).fetch();

모든 열을 쿼리합니다.

List<Tuple> 행 = query.select(cat.all()).from(cat).fetch();
 

SQL로 쿼리하지만 엔터티로 프로젝트:

query = new JPASQLQuery<Void>(entityManager, 템플릿);
List<Cat> cats = query.select(catEntity).from(cat).orderBy(cat.name.asc()).fetch();

조인을 사용한 쿼리:

query = new JPASQLQuery<Void>(entityManager, 템플릿);
고양이 = query.select(catEntity).from(cat)
    .innerJoin(mate).on(cat.mateId.eq(mate.id))
    .where(cat.dtype.eq( "고양이" ), mate.dtype.eq( "고양이" ))
    .술책();

DTO에 쿼리하고 투영합니다.

query = new JPASQLQuery<Void>(entityManager, 템플릿);
List<CatDTO> catDTOs = query.select(Projections.constructor(CatDTO.class , cat.id, cat.name))
    .from(고양이)
    .orderBy(cat.name.asc())
    .술책();

JPA API 대신 Hibernate API를 사용하는 경우 HibernateSQLQuery대신 사용하십시오.

2.2. JDO 쿼리

Querydsl은 지속형 도메인 모델 데이터를 기반으로 쿼리하기 위한 일반적인 정적인 형식의 구문을 정의합니다. JDO와 JPA는 Querydsl의 주요 통합 기술입니다. 이 가이드에서는 JDO와 함께 Querydsl을 사용하는 방법을 설명합니다.

2.2.1. 메이븐 통합

Maven 프로젝트에 다음 종속성을 추가합니다.

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-apt </artifactId> 
  <version> ${querydsl.version} </version> 
  <scope> 제공 </scope> 
</dependent>

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-jdo </artifactId> 
  <version> ${querydsl.version} </version> 
</dependent>

이제 Querydsl에서 사용하는 쿼리 유형을 생성하는 Maven APT 플러그인을 구성합니다.

<프로젝트> 
  <빌드> 
    <플러그인>
      ...
      <plugin> 
        <groupId> com.mysema.maven </groupId> 
        <artifactId> apt-maven-plugin </artifactId> 
        <version> 1.1.3 </version> 
        <executions> 
          <execution> 
            <goals> 
              <goal> 프로세스 </goal> 
            </goals> 
            <configuration> 
              <outputDirectory> target/generated-sources/java </outputDirectory> 
              <processor> com.querydsl.apt.jdo.JDOAnnotationProcessor </processor> 
            </configuration> 
          </execution> 
        < /실행> </ 
      플러그인 >
    ...
    </플러그인> 
  </build> 
</project>

JDOAnnotationProcessor는 javax.jdo.annotations.PersistenceCapable주석이 달린 도메인 유형을 찾고 이에 대한 쿼리 유형을 생성합니다.

새로 설치를 실행하면 target/generated-sources/java에 쿼리 유형이 생성됩니다.

Eclipse를 사용하는 경우 mvn eclipse:eclipse를 실행하여 target/generated-sources/java를 소스 폴더로 포함하도록 Eclipse 프로젝트를 업데이트하십시오.

이제 JDO 쿼리 인스턴스와 쿼리 도메인 모델의 인스턴스를 구성할 수 있습니다.

2.2.2. 개미 통합

full-deps 번들의 jar 파일을 클래스 경로에 배치하고 Querydsl 코드 생성을 위해 다음 작업을 사용합니다.

    <!-- APT 기반 코드 생성 --> 
    <javac  srcdir = "${src}"  classpathref = "cp" > 
      <compilerarg  value = "-proc:only" /> 
      <compilerarg  value = "-processor" /> 
      < compilerarg  값 = "com.querydsl.apt.jdo.JDOAnnotationProcessor" /> 
      <compilerarg  값 = "-s" /> 
      <compilerarg  값 = "${generated}" /> 
    </javac>

    <!-- 컴파일 --> 
    <javac  classpathref = "cp"  destdir = "${build}" > 
      <src  경로 = "${src}" /> 
      <src  경로 = "${generated}" /> 
    </ javac>

src를 생성된 소스용 폴더로 생성된 기본 소스 폴더로 바꾸고 대상 폴더로 빌드합니다 .

2.2.3. 쿼리 유형 사용

Querydsl로 쿼리를 생성하려면 변수와 쿼리 구현을 인스턴스화해야 합니다. 변수부터 시작하겠습니다.

프로젝트에 다음과 같은 도메인 유형이 있다고 가정해 보겠습니다.

@PersistenceCapable
 공개  클래스 고객 {
   개인 문자열 firstName;
  개인 문자열 성;

  공개 문자열 getFirstName() {
     return firstName;
  }

  공개 문자열 getLastName() {
     return lastName;
  }

  공공  무효 setFirstName(문자열 fn) {
    이름 = fn;
  }

  공공  무효 setLastName(문자열 ln) {
    성 = ln;
  }
}

Querydsl은 Customer와 동일한 패키지에 QCustomer라는 간단한 이름을 가진 쿼리 유형을 생성합니다. QCustomer는 Customer 유형을 대표하는 Querydsl에서 정적으로 유형이 지정된 변수로 사용될 수 있습니다.

QCustomer에는 정적 필드로 액세스할 수 있는 기본 인스턴스 변수가 있습니다.

QCustomer 고객 = QCustomer.customer;

또는 다음과 같이 고유한 Customer 변수를 정의할 수 있습니다.

QCustomer 고객 = new QCustomer( "myCustomer" );

QCustomer는 원래 유형 Customer 유형의 모든 속성을 공개 필드로 반영합니다. firstName 필드는 다음과 같이 액세스할 수 있습니다.

고객.첫번째이름;

2.2.4. JDO로 쿼리하기

JDO 모듈의 경우 JDOQuery기본 쿼리 구현입니다. 다음과 같이 인스턴스화됩니다.

지속성 관리자 pm = ...;
JDOQuery<?> 쿼리 = new JDOQuery<Void>(pm);

이 장의 예에서는 쿼리가 인스턴스를 통해 생성됩니다 JDOQueryFactory. JDOQueryFactory인스턴스를 얻으려면 선호되는 옵션이어야 합니다 JDOQuery.

이름이 Bob인 고객을 검색하려면 다음과 같은 쿼리를 구성합니다.

QCustomer 고객 = QCustomer.customer;
고객 bob = queryFactory.selectFrom(고객)
                   .where(customer.firstName.eq( "밥" ))
                   .fetchOne();

selectFrom 호출은 쿼리 소스와 프로젝션을 정의하고, where 부분은 필터를 정의하고 fetchOne은 Querydsl에 단일 요소를 반환하도록 지시합니다. 쉽지요?

또는 다음과 같이 표현할 수도 있습니다.

QCustomer 고객 = QCustomer.customer;
고객 bob = queryFactory.select(고객).from(고객)
                   .where(customer.firstName.eq( "밥" ))
                   .fetchOne();

여러 소스로 쿼리를 생성하려면 다음과 같이 JDOQuery 클래스를 사용하면 됩니다.

QCustomer 고객 = QCustomer.customer;
Q회사 회사 = QCompany.company;
query.from(고객, 회사);

여러 필터를 사용하려면 다음과 같이 사용하십시오.

queryFactory.selectFrom(고객)
    .where(customer.firstName.eq( "밥" ), customer.lastName.eq( "윌슨" ));

아니면 이렇게

queryFactory.selectFrom(고객)
    .where(customer.firstName.eq( "Bob" ).and(customer.lastName.eq( "Wilson" )));

"or"를 통해 필터를 결합하려면 다음 패턴을 사용하십시오.

queryFactory.selectFrom(고객)
    .where(customer.firstName.eq( "Bob" ).or(customer.lastName.eq( "Wilson" )));

2.2.5. 일반적인 사용법

다음과 같이 JDOQuery 클래스의 계단식 메소드를 사용하십시오.

select: 쿼리의 투영을 설정합니다. (쿼리 팩토리를 통해 생성된 경우 필요하지 않음)

from: 여기에 쿼리 소스를 추가합니다. 첫 번째 인수가 기본 소스가 되고 나머지는 변수로 처리됩니다.

여기서: 쉼표로 구분된 가변 인수 형식 또는 and 연산자를 통해 계단식으로 연결된 쿼리 필터를 추가합니다.

groupBy: varargs 형식의 인수별로 그룹을 추가합니다.

가지고: "그룹화 기준" 그룹화의 필터를 조건자 표현식의 varargs 배열로 추가합니다.

orderBy: 결과의 순서를 순서 표현식의 varargs 배열로 추가합니다. OrderSpecifier 인스턴스에 액세스하려면 숫자, 문자열 및 기타 유사한 표현식에 asc() 및 desc()를 사용하십시오.

제한, 오프셋, 제한: 결과의 페이징을 설정합니다. 최대 결과에 대한 제한, 행 건너뛰기에 대한 오프셋 및 한 번의 호출로 둘 다를 정의하기 위한 제한.

2.2.6. 주문

순서를 선언하는 구문은 다음과 같습니다.

QCustomer 고객 = QCustomer.customer;
queryFactory.selectFrom(고객)
    .orderBy(고객.lastName.asc(), 고객.firstName.desc())
    .술책();

2.2.7. 그룹화

그룹핑은 다음과 같은 형태로 할 수 있습니다.

queryFactory.select(고객.라스트이름).from(고객)
    .groupBy(고객.성명)
    .술책();

2.2.8. 조항 삭제

Querydsl JDO의 삭제 절은 간단한 삭제 위치 실행 형식을 따릅니다. 여기 몇 가지 예가 있어요.

QCustomer 고객 = QCustomer.customer;
// 모든 고객 삭제
queryFactory.delete(고객).execute();
// 레벨 3 미만의 모든 고객 삭제 
queryFactory.delete(customer).where(customer.level.lt( 3 )).execute();

JDODeleteClause 생성자의 두 번째 매개변수는 삭제할 엔터티입니다. where 호출은 선택 사항이며 실행 호출은 삭제를 수행하고 삭제된 항목의 양을 반환합니다.

2.2.9. 하위 쿼리

하위 쿼리를 생성하려면 팩토리 메소드 중 하나를 사용하고 JDOExpressions from, where 등을 통해 쿼리 매개변수를 추가 할 수 있습니다.

QDepartment 부서 = QDepartment.department;
QDepartment d = new QDepartment( "d" );
queryFactory.selectFrom(부서)
    .where(department.size.eq(JDOExpressions.select(d.size.max()).from(d))
    .술책();

다음 기본 JDO 쿼리를 나타냅니다.

com.querydsl.jdo.models.company.Department에서 이것을 선택하십시오.
this.size == 위치
(com.querydsl.jdo.models.company.Department d에서 최대(d.size) 선택)
    

다른 예시

QEmployee 직원 = QEmployee.employee;
QEmployee e = new QEmployee( "e" );
queryFactory.selectFrom(직원)
    .where(employee.weeklyhours.gt(
        JDOExpressions.select(e.weeklyhours.avg())
                      .from(employee.department.employees, e)
                      .where(e.manager.eq(employee.manager)))
    .술책();

이는 다음 기본 JDO 쿼리를 나타냅니다.

com.querydsl.jdo.models.company.Employee에서 이것을 선택하세요.
여기가 어디인가요.주간시간 >
(this.department.employees e WHERE e.manager == this.manager에서 평균(e.weeklyhours) 선택)
    

2.2.10. 네이티브 SQL 사용

Querydsl은 클래스를 통해 JDO의 기본 SQL을 지원합니다 JDOSQLQuery.

이를 사용하려면 SQL 스키마에 대한 Querydsl 쿼리 유형을 생성해야 합니다. 예를 들어 다음 Maven 구성을 사용하여 이 작업을 수행할 수 있습니다.

<프로젝트> 
  <빌드> 
    <플러그인>
      ...
      <plugin> 
        <groupId> com.querydsl </groupId> 
        <artifactId> querydsl-maven-plugin </artifactId> 
        <version> ${querydsl.version} </version> 
        <executions> 
          <execution> 
            <goals> 
              <goal> 내보내기 </goal> 
            </goals> 
          </execution> 
        </executions> 
        <configuration> 
          <jdbcDriver> org.apache.derby.jdbc.EmbeddedDriver </jdbcDriver> 
          <jdbcUrl> jdbc:derby:target/demoDB;create=true </jdbcUrl> 
          <packageName> com.mycompany.mydomain </packageName> 
          <targetFolder> ${project.basedir}/target/generated-sources/java </targetFolder> 
        </configuration> <종속성> < 
        종속성 
          > 
            <groupId> org.apache.derby </groupId> 
            <artifactId> 더비 </artifactId> 
            <version> ${derby.version} </version> 
          </dependent> 
        </dependent> 
      </plugin>
      ...
    </플러그인> 
  </build> 
</project>

쿼리 유형이 선택한 위치에 성공적으로 생성되면 쿼리에 사용할 수 있습니다.

단일 열 쿼리:

// 직렬화 템플릿 
SQLTemplates template = new DerbyTemplates();
// 쿼리 유형(SQL의 경우 S*, 도메인 유형의 경우 Q*) 
SAnimal cat = new SAnimal( "cat" );
SAnimal 메이트 = new SAnimal( "메이트" );

JDOSQLQuery<?> 쿼리 = new JDOSQLQuery<Void>(pm, 템플릿);
List<String> names = query.select(cat.name).from(cat).fetch();

여러 열 쿼리:

query = new JDOSQLQuery<Void>(pm, 템플릿);
List<Tuple> 행 = query.select(cat.id, cat.name).from(cat).fetch();

모든 열을 쿼리합니다.

List<Tuple> 행 = query.select(cat.all()).from(cat).fetch();
 

조인을 사용한 쿼리:

query = new JDOSQLQuery<Void>(pm, 템플릿);
고양이 = query.select(catEntity).from(cat)
    .innerJoin(mate).on(cat.mateId.eq(mate.id))
    .where(cat.dtype.eq( "고양이" ), mate.dtype.eq( "고양이" ))
    .술책();

DTO에 쿼리하고 투영합니다.

query = new JDOSQLQuery<Void>(pm, 템플릿);
List<CatDTO> catDTOs = query.select(Projections.constructor(CatDTO.class , cat.id, cat.name))
    .from(고양이)
    .orderBy(cat.name.asc())
    .술책();

2.3. SQL 쿼리

이 장에서는 SQL 모듈의 쿼리 유형 생성 및 쿼리 기능에 대해 설명합니다.

2.3.1. 메이븐 통합

Maven 프로젝트에 다음 종속성을 추가합니다.

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-sql </artifactId> 
  <version> ${querydsl.version} </version> 
</dependent>

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-sql-codegen </artifactId> 
  <version> ${querydsl.version} </version> 
  <scope> 제공 </scope> 
</dependent>

Maven을 통해 코드가 생성되는 경우 querydsl-sql-codegen 종속성을 건너뛸 수 있습니다.

2.3.2. Maven을 통한 코드 생성

이 기능은 주로 Maven 플러그인을 통해 사용해야 합니다. 예는 다음과 같습니다.

<프로젝트> 
  <빌드> 
    <플러그인>
      ...
      <plugin> 
        <groupId> com.querydsl </groupId> 
        <artifactId> querydsl-maven-plugin </artifactId> 
        <version> ${querydsl.version} </version> 
        <executions> 
          <execution> 
            <goals> 
              <goal> 내보내기 </goal> 
            </goals> 
          </execution> 
        </executions> 
        <configuration> 
          <jdbcDriver> org.apache.derby.jdbc.EmbeddedDriver </jdbcDriver> 
          <jdbcUrl> jdbc:derby:target/demoDB;create=true </jdbcUrl> 
          <packageName> com.myproject.domain </packageName> 
          <targetFolder> ${project.basedir}/target/generated-sources/java </targetFolder> 
        </configuration> < 종속성> < 
        종속성 
          > 
            <groupId> org.apache.derby </groupId> 
            <artifactId> 더비 </artifactId> 
            <version> ${derby.version} </version> 
          </dependent> 
        </dependent> 
      </plugin>
      ...
    </플러그인> 
  </build> 
</project>

테스트 코드와 함께 사용할 테스트 소스 폴더로 대상 폴더를 처리하려면 목표 test-export를 사용하십시오.

표 2.1. 매개변수

이름설명
jdbc드라이버 JDBC 드라이버의 클래스 이름
jdbcUrl JDBC URL
jdbc사용자 JDBC 사용자
jdbc비밀번호 JDBC 비밀번호
이름접두사 생성된 쿼리 클래스의 이름 접두사(기본값: Q)
이름접미사 생성된 쿼리 클래스의 이름 접미사(기본값: )
콩접두사 생성된 Bean 클래스의 이름 접두어
bean접미사 생성된 Bean 클래스의 이름 접미사
패키지 이름 소스 파일을 생성해야 하는 패키지 이름
콩패키지 이름 Bean 파일을 생성해야 하는 패키지 이름, (기본값: packageName)
빈인터페이스 Bean 클래스에 추가할 인터페이스 클래스 이름 배열(기본값: 비어 있음)
beanAddToString 기본 toString() 구현을 생성하려면 true로 설정합니다(기본값: false).
beanAddFullConstructor 공개 빈 외에 전체 생성자를 생성하려면 true로 설정합니다. (기본값: false)
콩인쇄수퍼 유형 상위 유형도 인쇄하려면 true로 설정합니다. (기본값: false)
스키마 패턴 LIKE 패턴 형식의 스키마 이름 패턴. 데이터베이스에 저장된 스키마 이름과 일치해야 하며, 여러 개일 경우 쉼표로 구분할 수 있습니다(기본값: null).
테이블이름패턴 LIKE 패턴 형태의 테이블 이름 패턴; 데이터베이스에 저장된 테이블 이름과 일치해야 하며, 여러 개일 경우 쉼표로 구분할 수 있습니다. (기본값: null)
대상폴더 소스가 생성되어야 하는 대상 폴더
콩대상폴더 Bean 소스가 생성되어야 하는 대상 폴더, 기본값은 targetFolder와 동일한 값입니다.
명명전략클래스 NamingStrategy 클래스의 클래스 이름(기본값: DefaultNamingStrategy)
BeanSerializerClass BeanSerializer 클래스의 클래스 이름 (기본값: BeanSerializer)
serializerClass Serializer 클래스의 클래스 이름(기본값: MetaDataSerializer)
수출 콩 Bean도 생성하려면 true로 설정하십시오. 섹션 2.14.13을 참조하십시오(기본값: false).
innerClassesForKeys 키에 대한 내부 클래스를 생성하려면 true로 설정합니다(기본값: false).
검증주석 유효성 검사 주석의 직렬화를 활성화하려면 true로 설정합니다(기본값: false).
열주석 열 주석 내보내기(기본값: false)
createScalaSources Java 소스 대신 Scala 소스를 내보낼지 여부, (기본값: false)
스키마To패키지 패키지에 스키마 이름 추가(기본값: false)
소문자 이름의 소문자 변환(기본값: false)
내보내기테이블 테이블 내보내기(기본값: true)
내보내기보기 뷰 내보내기(기본값: true)
내보내기기본키 기본 키 내보내기(기본값: true)
내보낼 테이블 유형 내보낼 테이블 유형의 쉼표로 구분된 목록(허용되는 값은 JDBC 드라이버에 따라 다름) 임의의 유형 세트를 내보낼 수 있습니다(예: "TABLE, MATERIALIZED VIEW"). 이 매개변수가 설정된 경우 내보내기테이블 및 내보내기뷰 매개변수는 무시됩니다. (기본값: 없음)
외부 키 내보내기 외래 키 내보내기(기본값: true)
내보내기DirectForeignKeys 직접 외래 키 내보내기(기본값: true)
내보내기역외부키 역 외래 키 내보내기(기본값: true)
맞춤 유형 사용자 정의 사용자 유형(기본값: 없음)
유형매핑 table.column을 Java 유형으로 매핑(기본값: 없음)
숫자 매핑 Java 유형에 대한 크기/숫자 매핑(기본값: 없음)
수입품 생성된 쿼리 클래스에 추가된 Java 가져오기 배열: 패키지의 경우 com.bar (.* 표기법 없음), 클래스의 경우 com.bar.Foo (기본값: 비어 있음)
생성된AnnotationClass 생성된 소스에 추가할 단일 요소 주석 (문자열 요소 포함) 의 정규화된 클래스 이름입니다 . com.querydsl.core.annotations.Generated 에 빌드하면 Jacoco와 같은 바이트 코드 분석 도구에 사용할 수 있는 CLASS 보존 기능이 있습니다. (기본값: Java 버전에 따라 javax.annotation.Generated 또는 javax.annotation.processing.Generated ). 단일 요소 주석 도 참조하세요.

사용자 정의 유형을 사용하여 추가 유형 구현을 등록할 수 있습니다.

<customTypes> 
  <customType> com.querydsl.sql.types.InputStreamType </customType> 
</customTypes>

유형 매핑을 사용하여 table.column 특정 Java 유형을 등록할 수 있습니다.

<typeMappings> 
  <typeMapping> 
    <table> IMAGE </table> 
    <column> CONTENTS </column> 
    <type> java.io.InputStream </type> 
  </typeMapping> 
</typeMappings>

숫자 매핑의 기본값은 다음과 같습니다.

표 2.2. 숫자 매핑

총 자릿수소수점유형
> 18 0 빅정수
> 9 0
> 4 0 정수
> 2 0 짧은
> 0 0 바이트
> 0 > 0 BigDecimal

다음과 같이 특정 총계/소수 자릿수 조합에 맞게 사용자 정의할 수 있습니다.

<numericMappings> 
  <numericMapping> 
    <total> 1 </total> 
    <decimal> 0 </decimal> 
    <javaType> java.lang.Byte </javaType> 
  </numericMapping> 
</numericMappings>

가져오기를 사용하여 스키마 간 외래 키 지원을 추가할 수 있습니다.

플러그인을 사용하여 스키마, 테이블 및 열의 이름을 바꿀 수도 있습니다. 여기 몇 가지 예가 있어요.

스키마 이름 바꾸기:

<renameMappings> 
  <renameMapping> 
    <fromSchema> PROD </fromSchema> 
    <toSchema> TEST </toSchema> 
  </renameMapping> 
</renameMappings>

테이블 이름 바꾸기:

<renameMappings> 
  <renameMapping> 
    <fromSchema> PROD </fromSchema> 
    <fromTable> CUSTOMER </fromTable> 
    <toTable> CSTMR </toTable> 
  </renameMapping> 
</renameMappings>

열 이름 바꾸기:

<renameMappings> 
  <renameMapping> 
    <fromSchema> PROD </fromSchema> 
    <fromTable> CUSTOMER </fromTable> 
    <fromColumn> ID </fromColumn> 
    <toColumn> IDX </toTable> 
  </renameMapping> 
</renameMappings>

참고: 테이블과 열의 이름을 바꿀 때 fromSchema를 생략할 수 있습니다.

APT 기반 코드 생성과 비교하여 QueryDelegate 주석 처리와 같은 특정 기능을 사용할 수 없습니다.

2.3.3. ANT를 통한 코드 생성

com.querydsl.sql.codegen.ant.AntMetaDataExporter querydsl-sql 모듈의 ANT 작업은 ANT 작업과 동일한 기능을 제공합니다. 작업의 구성 매개변수는 복합 유형을 제외하고 Maven 플러그인과 동일합니다.

복합 유형은 이 예와 같이 래퍼 요소 없이 사용됩니다.

<프로젝트  이름 = "testproject"  기본값 = "codegen"  basedir = "." >

  <taskdef  이름 = "codegen"  클래스 이름 = "com.querydsl.sql.codegen.ant.AntMetaDataExporter" />

  <대상  이름 = "codegen" > 
    <codegen 
      jdbcDriver = "org.h2.Driver" 
      jdbcUser = "sa" 
      jdbcUrl = "jdbc:h2:/dbs/db1" 
      packageName = "test" 
      targetFolder = "target/generated-sources/ java" > 
      <renameMapping  fromSchema = "PUBLIC"  toSchema = "PUB" /> 
    </codegen> 
  </target> 
</project>

2.3.4. 쿼리 유형 만들기

시작하려면 다음과 같이 스키마를 Querydsl 쿼리 유형으로 내보내세요.

java.sql.Connection conn = ...;
MetaDataExporter 내보내기 = new MetaDataExporter();
importer.setPackageName( "com.myproject.mydomain" );
importer.setTargetFolder( new File( "target/generated-sources/java" ));
수출업자.수출(conn.getMetaData());

이는 데이터베이스 스키마가 target/generated-sources/java 폴더의 com.myproject.domain 패키지에 미러링됨을 선언합니다.

생성된 유형에는 클래스 이름과 같이 대소문자 혼합으로 변환된 테이블 이름과 쿼리 유형에서 속성 경로로 사용할 수 있는 열에 적용된 유사한 대소문자 혼합 변환이 있습니다.

이 기본 키 및 외래 키 제약 조건 외에도 압축 조인 선언에 사용할 수 있는 필드가 제공됩니다.

2.3.5. 구성

구성은 Querydsl SQL 언어를 인수로 사용하는 com.querydsl.sql.Configuration 클래스를 통해 수행됩니다. H2의 경우 다음과 같이 생성합니다.

SQLTemplates 템플릿 = new H2Templates();
구성 구성 = 새 구성(템플릿);

Querydsl은 SQL 방언을 사용하여 다양한 관계형 데이터베이스에 필요한 SQL 직렬화를 사용자 정의합니다. 사용 가능한 방언은 다음과 같습니다.

  • CUBRID템플릿 (CUBRID 8.4에서 테스트)
  • DB2Templates(DB2 10.1.2로 테스트됨)
  • DerbyTemplates(Derby 10.8.2.2로 테스트됨)
  • Firebird템플릿(Firebird 2.5로 테스트됨)
  • HSQLDBTemplates(HSQLDB 2.2.4로 테스트됨)
  • H2Template(H2 1.3.164로 테스트됨)
  • MySQLTemplates(MySQL 5.5로 테스트됨)
  • OracleTemplates(Oracle 10 및 11로 테스트)
  • PostgreSQL템플릿(PostgreSQL 9.1로 테스트됨)
  • SQLiteTemplates(xerial JDBC 3.7.2로 테스트됨)
  • SQLServerTemplates(SQL Server로 테스트됨)
  • SQLServer2005템플릿(SQL Server 2005용)
  • SQLServer2008템플릿(SQL Server 2008용)
  • SQLServer2012Templates(SQL Server 2012 이상용)
  • TeradataTemplate(Teradata 14로 테스트)

사용자 정의된 SQLTemplates 인스턴스의 경우 다음과 같은 빌더 패턴을 사용할 수 있습니다.

  H2Templates.builder()
     .printSchema() // 출력에 스키마를 포함합니다 
     . .quote()        // 이름을 인용합니다 
     . .newLineToSingleSpace() // 출력에서 ​​새 줄을 단일 공백으로 바꿉니다 
     . .escape(ch)     // 이스케이프 문자를 설정합니다. 
     .짓다();      // 사용자 정의된 SQLTemplates 인스턴스를 가져옵니다.

Configuration 클래스의 메소드를 사용하면 setUseLiterals(true)를 통해 리터럴을 직접 직렬화하고, 스키마와 테이블을 재정의하고, 사용자 정의 유형을 등록할 수 있습니다. 자세한 내용은 구성의 javadoc을 참조하세요.

2.3.6. 쿼리 중

다음 예에서는 쿼리 생성을 위해 클래스를 사용합니다 SQLQueryFactory. 이를 사용하면 생성자 기반 쿼리 생성에 비해 코드가 더 간결해집니다.

SQLQueryFactory queryFactory = new SQLQueryFactory(구성, 데이터소스);

Querydsl SQL을 사용한 쿼리는 다음과 같이 간단합니다.

QCustomer 고객 = new QCustomer( "c" );

List<String> lastNames = queryFactory.select(customer.lastName).from(고객)
    .where(customer.firstName.eq( "밥" ))
    .술책();

이는 관련 테이블 이름이 customer 이고 열 first_name  last_name 이라고 가정하여 다음 SQL 쿼리로 변환됩니다 .

SELECT c.성명
고객 C로부터
WHERE c.first_name = '밥'

2.3.7. 일반적인 사용법

다음과 같이 SQLQuery 클래스의 계단식 메소드를 사용하십시오.

select: 쿼리의 투영을 설정합니다. (쿼리 팩토리를 통해 생성된 경우 필요하지 않음)

from: 여기에 쿼리 소스를 추가합니다.

innerJoin, Join, leftJoin, rightJoin, fullJoin, on: 이러한 구성을 사용하여 조인 요소를 추가합니다. 조인 방법의 경우 첫 번째 인수는 조인 소스이고 두 번째 인수는 대상(별칭)입니다.

여기서: 쉼표로 구분된 가변 인수 형식 또는 and 연산자를 통해 계단식으로 연결된 쿼리 필터를 추가합니다.

groupBy: varargs 형식의 인수별로 그룹을 추가합니다.

가지고: "그룹화 기준" 그룹화의 필터를 조건자 표현식의 varags 배열로 추가합니다.

orderBy: 결과의 순서를 순서 표현식의 varargs 배열로 추가합니다. OrderSpecifier 인스턴스에 액세스하려면 숫자, 문자열 및 기타 유사한 표현식에 asc() 및 desc()를 사용하십시오.

제한, 오프셋, 제한: 결과의 페이징을 설정합니다. 최대 결과에 대한 제한, 행 건너뛰기에 대한 오프셋 및 한 번의 호출로 둘 다를 정의하기 위한 제한.

2.3.8. 조인

조인은 다음 구문을 사용하여 구성됩니다.

QCustomer 고객 = QCustomer.customer;
Q회사 회사 = QCompany.company;
queryFactory.select(고객.첫번째이름, 고객.라스트이름, 회사.이름)
    .from(고객)
    .innerJoin(고객.회사, 회사)
    .술책();

그리고 왼쪽 조인의 경우:

queryFactory.select(고객.첫번째이름, 고객.라스트이름, 회사.이름)
    .from(고객)
    .leftJoin(고객.회사, 회사)
    .술책();

또는 조인 조건을 작성할 수도 있습니다.

queryFactory.select(고객.첫번째이름, 고객.라스트이름, 회사.이름)
    .from(고객)
    .leftJoin(회사).on(customer.company.eq(회사))
    .술책();

2.3.9. 주문

순서를 선언하는 구문은 다음과 같습니다.

queryFactory.select(고객.firstName, 고객.lastName)
    .from(고객)
    .orderBy(고객.lastName.asc(), 고객.firstName.asc())
    .술책();

이는 다음 기본 SQL과 동일합니다.

SELECT c.이름, c.성 이름
고객 C로부터
ORDER BY c.last_name ASC, c.first_name ASC

2.3.10. 그룹화

그룹핑은 다음과 같은 형태로 할 수 있습니다.

queryFactory.select(고객.라스트이름)
    .from(고객)
    .groupBy(고객.성명)
    .술책();

이는 다음 기본 SQL과 동일합니다.

SELECT c.성명
고객 C로부터
GROUP BY c.성_이름

2.3.11. 하위 쿼리 사용

하위 쿼리를 생성하려면 팩토리 메소드 중 하나를 사용하고 SQLExpressions from, where 등을 통해 쿼리 매개변수를 추가 할 수 있습니다.

QCustomer 고객 = QCustomer.customer;
QCustomer 고객2 = new QCustomer( "고객2" );
queryFactory.select(고객.all())
    .from(고객)
    .where(고객.상태.eq(
        SQLExpressions.select(customer2.status.max()).from(customer2)))
    .술책()

다른 예시

QStatus 상태 = QStatus.status;
queryFactory.select(고객.all())
    .from(고객)
    .where(고객.상태.in(
        SQLExpressions.select(status.id).from(status).where(status.level.lt( 3 ))))
    .술책();

2.3.12. 리터럴 선택

리터럴을 선택하려면 다음과 같이 상수 인스턴스를 생성해야 합니다.

queryFactory.select(Expressions.constant( 1 ),
                    Expressions.constant( "abc" ));

이 클래스는 com.querydsl.core.types.dsl.Expressions투영, 작업 및 템플릿 생성을 위한 기타 유용한 정적 메서드도 제공합니다.

2.3.13. 쿼리 확장 지원

엔진별 구문을 지원하는 사용자 정의 쿼리 확장은 AbstractSQLQuery를 서브클래싱하고 주어진 MySQLQuery 예제와 같이 플래그 지정 메서드를 추가하여 생성할 수 있습니다.

공개  클래스 MySQLQuery<T>는 AbstractSQLQuery<T, MySQLQuery<T>>를 확장합니다 .

    public MySQLQuery(Connection conn) {
         this (conn, new MySQLTemplates(), new DefaultQueryMetadata());
    }

    public MySQLQuery(Connection conn, SQLTemplates template) {
         this (conn, template, new DefaultQueryMetadata());
    }

    protected MySQLQuery(연결 conn, SQLTemplates 템플릿, QueryMetadata 메타데이터) {
         super (conn, 새 구성(템플릿), 메타데이터);
    }

    public MySQLQuery bigResult() {
         return addFlag(Position.AFTER_SELECT, "SQL_BIG_RESULT " );
    }

    public MySQLQuery bufferResult() {
         return addFlag(Position.AFTER_SELECT, "SQL_BUFFER_RESULT " );
    }


    // ...
}

플래그는 직렬화의 특정 지점에 삽입할 수 있는 사용자 정의 SQL 조각입니다. 지원되는 위치는 enum 클래스의 enum입니다 com.querydsl.core.QueryFlag.Position.

2.3.14. 창 기능

창 기능은 클래스의 메서드를 통해 Querydsl에서 지원됩니다 SQLExpressions.

사용 예:

queryFactory.select(SQLExpressions.rowNumber()
        .위에()
        .partitionBy(직원.이름)
        .orderBy(직원.id))
     .from(직원)

2.3.15. 공통 테이블 표현식

공통 테이블 표현식은 두 가지 구문 변형을 통해 Querydsl SQL에서 지원됩니다.

QEmployee 직원 = QEmployee.employee;
queryFactory.with(직원, SQLExpressions.select(employee.all)
                                          .from(직원)
                                          .where(employee.name.startsWith( "A" )))
            .에서(...)

그리고 열 목록을 사용하여

QEmployee 직원 = QEmployee.employee;
queryFactory.with(직원, 직원 ID, 직원.이름)
            .as(SQLExpressions.select(직원.id, 직원.이름)
                              .from(직원)
                              .where(employee.name.startsWith( "A" )))
            .에서(...)

공통 테이블 표현식의 열이 기존 테이블 또는 뷰의 하위 집합인 경우 생성된 경로 유형을 사용하는 것이 좋습니다(예: 이 경우 QEmployee). 그러나 열이 기존 테이블에 맞지 않으면 PathBuilder를 사용할 수 있습니다. 대신에.

아래는 그러한 경우의 예이다

QEmployee 직원 = QEmployee.employee;
QDepartment 부서 = QDepartment.department;
PathBuilder<Tuple> emp = new PathBuilder<Tuple>(Tuple.class , " emp" );
queryFactory.with(emp, SQLExpressions.select(employee.id, 직원.이름, 직원.departmentId,
                                          부서.이름.as( "부서이름" ))
                                      .from(직원)
                                      .innerJoin(department).on(employee.departmentId.eq(department.id))))
            .에서(...)

2.3.16. 기타 SQL 표현식

SQLExpressions다른 SQL 표현식도 클래스에서 정적 메서드로 사용할 수 있습니다 .

2.3.17. 데이터 조작 명령 사용

2.3.17.1. 끼워 넣다

기둥 포함

QSurvey 설문조사 = QSurvey.survey;

queryFactory.insert(설문조사)
    .columns(설문조사.id, 설문조사.이름)
    .values( 3 , "안녕하세요" ).execute();

기둥 없음

queryFactory.insert(설문조사)
    .values( 4 , "안녕하세요" ).execute();

하위 쿼리 포함

queryFactory.insert(설문조사)
    .columns(설문조사.id, 설문조사.이름)
    .select(SQLExpressions.select(survey2.id.add( 1 ), Survey2.name).from(survey2))
    .실행하다();

하위 쿼리 있음, 열 없음

queryFactory.insert(설문조사)
    .select(SQLExpressions.select(survey2.id.add( 10 ), Survey2.name).from(survey2))
    .실행하다();

열/값 사용법의 대안으로 Querydsl은 다음과 같이 사용할 수 있는 set 메소드도 제공합니다.

QSurvey 설문조사 = QSurvey.survey;

queryFactory.insert(설문조사)
    .set(survey.id, 3 )
    .set(survey.name, "안녕하세요" ).execute();

이는 첫 번째 예와 동일합니다. set 메소드의 사용은 항상 내부적으로 열과 값으로 확장됩니다.

조심하세요

열(...).선택(...)

삽입할 주어진 쿼리의 결과 집합을 매핑하는 반면

수정된 행 수 대신 생성된 키를 가져오려면 excuteWithKey/s 메소드 중 하나를 사용하세요.

세트(...)

단일 열을 매핑하고 null은 빈 하위 쿼리 결과에 사용됩니다.

Bean의 내용을 기반으로 절 인스턴스를 채우려면 다음을 사용할 수 있습니다.

queryFactory.insert(설문조사)
    .populate(surveyBean).execute();

null 바인딩이 필요한 경우 null 바인딩이 제외됩니다.

queryFactory.insert(설문조사)
    .populate(surveyBean, DefaultMapper.WITH_NULL_BINDINGS).execute();

2.3.17.2. 업데이트

어디서

QSurvey 설문조사 = QSurvey.survey;

queryFactory.update(설문조사)
    .where(survey.name.eq( "XXX" ))
    .set(설문조사.이름, "S" )
    .실행하다();

어디에도 없이

queryFactory.update(설문조사)
    .set(설문조사.이름, "S" )
    .실행하다();

콩 개체수 사용

queryFactory.update(설문조사)
    .populate(surveyBean)
    .실행하다();

2.3.17.3. 삭제

어디서

QSurvey 설문조사 = QSurvey.survey;

queryFactory.delete(설문조사)
    .where(survey.name.eq( "XXX" ))
    .실행하다();

어디에도 없이

queryFactory.delete(설문조사)
    .실행하다()

2.3.18. DML 절의 일괄 지원

Querydsl SQL은 DML API를 통해 JDBC 일괄 업데이트 사용을 지원합니다. 비슷한 구조의 연속 DML 호출이 있는 경우 addBatch() 사용을 통해 호출을 하나의 DMLClause로 묶을 수 있습니다. UPDATE, DELETE 및 INSERT에 대해 어떻게 작동하는지 예제를 참조하세요.

업데이트:

QSurvey 설문조사 = QSurvey.survey;

queryFactory.insert(survey).values( 2 , "A" ).execute();
queryFactory.insert(survey).values( 3 , "B" ).execute();

SQLUpdateClause 업데이트 = queryFactory.update(survey);
update.set(survey.name, "AA" ).where(survey.name.eq( "A" )).addBatch();
update.set(survey.name, "BB" ).where(survey.name.eq( "B" )).addBatch();

삭제:

queryFactory.insert(survey).values( 2 , "A" ).execute();
queryFactory.insert(survey).values( 3 , "B" ).execute();

SQLDeleteClause delete = queryFactory.delete(survey);
delete.where(survey.name.eq( "A" )).addBatch();
delete.where(survey.name.eq( "B" )).addBatch();
주장Equals( 2 , delete.execute());

끼워 넣다:

SQLInsertClause insert = queryFactory.insert(survey);
insert.set(survey.id, 5 ).set(survey.name, "5" ).addBatch();
insert.set(survey.id, 6 ).set(survey.name, "6" ).addBatch();
주장Equals( 2 , insert.execute());

2.3.19. Bean 클래스 생성

스키마 테이블에 대한 JavaBean DTO 유형을 생성하려면 다음과 같이 MetaDataExporter를 사용하십시오.

java.sql.Connection conn = ...;
MetaDataExporter 내보내기 = new MetaDataExporter();
importer.setPackageName( "com.myproject.mydomain" );
내보내기.setTargetFolder( 새 파일( "src/main/java" ));
importer.setBeanSerializer( new BeanSerializer());
수출업자.수출(conn.getMetaData());

이제 빈 유형을 DML 절의 채우기 메소드에 대한 인수로 사용할 수 있으며 쿼리에서 빈 유형으로 직접 프로젝션할 수 있습니다. 다음은 JUnit 형식의 간단한 예입니다.

QEmployee e = new QEmployee( "e" );

// 
직원 삽입 Employee = new Employee();
Employee.setFirstname( "John" );
정수 id = queryFactory.insert(e).populate(employee).executeWithKey(e.id);
직원.setId(id);

// 
Employee.setLastname 업데이트( "Smith" );
주장Equals( 1l , queryFactory.update(e).populate(employee).where(e.id.eq(employee.getId())).execute());

// 
직원 쿼리 smith = queryFactory.selectFrom(e).where(e.lastname.eq( "Smith" )).fetchOne();
주장Equals( "John" , smith.getFirstname());

// 삭제 
assertEquals( 1l , queryFactory.delete(e).where(e.id.eq(employee.getId())).execute());

2.3.20. SQL 쿼리 및 바인딩 추출

SQL 쿼리 및 바인딩은 getSQL 메서드를 통해 추출할 수 있습니다.

SQLBindings 바인딩 = query.getSQL();
System.out.println(bindings.getSQL());

SQL 문자열의 모든 리터럴도 필요한 경우 setUseLiterals(true)를 통해 쿼리 또는 구성 수준에서 리터럴 직렬화를 활성화할 수 있습니다.

2.3.21. 맞춤 유형

Querydsl SQL은 ResultSet/Statement 상호 작용을 위한 사용자 정의 유형 매핑을 선언할 수 있는 가능성을 제공합니다. 사용자 정의 유형 매핑은 실제 쿼리에 생성자 인수로 제공되는 com.querydsl.sql.Configuration 인스턴스에서 선언할 수 있습니다.

구성 구성 = 새 구성( 새 H2Templates());
// Types.DATE에 대한 매핑을 재정의합니다 
.config.register( new UtilDateType());

그리고 테이블 열의 경우

구성 구성 = 새 구성( 새 H2Templates());
// person 테이블의 성별 열에 대한 매핑을 선언합니다 
.configuration.register( "person" , "gender" ,   new EnumByNameType<Gender>(Gender.class ) );

숫자 매핑을 사용자 정의하려면 다음과 같은 RegisterNumeric 메소드를 사용할 수 있습니다.

구성.registerNumeric( 5 , 2 , Float.class );

그러면 Float 유형이 NUMERIC(5,2) 유형에 매핑됩니다.

2.3.22. 쿼리 및 절 듣기

SQLListener는 쿼리 및 DML 절을 수신하는 데 사용할 수 있는 리스너 인터페이스입니다. SQLListener 인스턴스는 addListener 메소드를 통해 구성 및 쿼리/절 수준에서 등록할 수 있습니다.

리스너의 사용 사례는 데이터 동기화, 로깅, 캐싱 및 검증입니다.

2.3.23. 스프링 통합

Querydsl SQL은 querydsl-sql-spring 모듈을 통해 Spring과 통합됩니다.

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-sql-spring </artifactId> 
  <version> ${querydsl.version} </version> 
</dependent>

이는 Spring 트랜잭션 관리자와 함께 Querydsl SQL을 사용하기 위한 Spring 예외 변환 및 Spring 연결 공급자를 제공합니다. 다음은 구성 예입니다.

패키지 com.querydsl.example.config;

import com.querydsl.sql.H2Templates;
import com.querydsl.sql.SQLQueryFactory;
import com.querydsl.sql.SQLTemplates;
import com.querydsl.sql.spring.SpringConnectionProvider;
import com.querydsl.sql.spring.SpringExceptionTranslator;
import com.querydsl.sql.types.DateTimeType;
import com.querydsl.sql.types.LocalDateType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
org.springframework.context.annotation.PropertySource를 가져옵니다 .
org.springframework.core.env.Environment
 가져오기 ; org.springframework.jdbc.datasource.DataSourceTransactionManager를
 가져옵니다 . org.springframework.transaction.PlatformTransactionManager 가져오기 ;

import javax.sql.DataSource;
import java.sql.Connection;

@Configuration
 공개  클래스 JdbcConfiguration {

    @Bean
     public DataSource dataSource() {
         // 구현 생략
    }

    @Bean
     public PlatformTransactionManager transactionManager() {
         return  new DataSourceTransactionManager(dataSource());
    }

    @Bean
     공개 com.querydsl.sql.Configuration querydslConfiguration() {
        SQLTemplates 템플릿 = H2Templates.builder().build(); //템플릿으로 변경 
        com.querydsl.sql.Configuration 구성 = new com.querydsl.sql.Configuration(templates);
        구성.setExceptionTranslator( new SpringExceptionTranslator());
        반환 구성;
    }

    @Bean
     공개 SQLQueryFactory queryFactory() {
        SpringConnectionProvider 공급자 = new SpringConnectionProvider(dataSource());
        새로운 SQLQueryFactory(querydslConfiguration(), 공급자)를 반환합니다 . 
    }

}

2.4. Querydsl 공간

공간 쿼리에 대한 지원은 SQL 모듈의 확장 모듈인 Querydsl Spatial 모듈을 통해 제공됩니다. Spatial 모듈은 쿼리 및 개체 바인딩에서 Simple Feature Access의 개체 모델을 지원합니다.

개체 모델에는 geolatte 프로젝트가 사용 됩니다 .

 

2.4.1. 메이븐 통합

Maven 프로젝트에 다음 종속성을 추가합니다.

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-sql-spatial </artifactId> 
  <version> ${querydsl.version} </version> 
</dependent>

또한 다음과 같은 데이터베이스별 추가 종속성이 있습니다.

<!-- PostgreSQL 사용의 경우 --> 
<dependent> 
  <groupId> org.postgis </groupId> 
  <artifactId> postgis-jdbc </artifactId> 
  <version> 1.3.3 </version> 
  <scope> 제공됨 </scope > 
</의존성>

<!-- Oracle 사용의 경우 --> 
<dependent> 
  <groupId> oracle </groupId> 
  <artifactId> sdoapi </artifactId> 
  <version> 11.2.0 </version> 
  <scope> 제공됨 </scope> 
</dependent >

2.4.2. Maven을 통한 코드 생성

Querydsl SQL의 코드 생성은 데이터베이스 스키마에서 공간 유형의 사용을 감지하고 이러한 경우 공간 속성을 통해 지리학 유형을 사용하도록 설정할 수 있습니다.

<프로젝트> 
  <빌드> 
    <플러그인>
      ...
      <plugin> 
        <groupId> com.querydsl </groupId> 
        <artifactId> querydsl-maven-plugin </artifactId> 
        <version> ${querydsl.version} </version>
        ...
        <구성>
          ...
          <spatial> true </spatial> 
        </configuration> 
      </plugin>
      ...
    </플러그인> 
  </build> 
</project>

2.4.3. 런타임 구성

공간 모듈의 런타임 구성 측면은 일반적인 SQLTemplates 인스턴스 대신 공간 지원 인스턴스가 사용된다는 것입니다. 다음은 공간 지원 SQLTemplates 클래스 목록입니다.

  • GeoDB템플릿(H2용)
  • MySQLSpatial템플릿
  • OracleSpatialTemplate(알파 단계)
  • PostGIST템플릿
  • SQLServer2008SpatialTemplate
  • TeradataSpatial템플릿

2.4.4. 쿼리 중

공간 유형에 대한 코드 생성 및 런타임 구성 설정을 통해 이제 쿼리를 시도할 수 있습니다.

2.4.4.1. 거리로 필터링

기하점 = Wkt.fromWkt( "Point(2 2)" );
query.where(table.geo.distance(point).lt( 5.0 ));

형상 사이의 직선 거리 외에도 distanceSphere 및 distanceSpheroid를 통해 구형 및 구형 거리가 제공됩니다.

2.4.4.2. 포함

기하점 = Wkt.fromWkt( "Point(2 2)" );
query.where(table.geo.contains(point));

2.4.4.3. 교차로

기하학 geo = query.select(table.geo1.intersection(table.geo2)).fetchOne();

2.4.4.4. SPATIAL_REF_SYS 테이블에 대한 액세스

SPATIAL_REF_SYS 표준 테이블에 대한 통합 액세스는 QSpatialRefSys 및 SpatialRefSys 클래스를 통해 제공됩니다. SPATIAL_REF_SYS에는 지원되는 공간 참조 시스템에 대한 데이터가 포함되어 있습니다.

QSpatialRefSys SpatialRefSys = QSpatialRefSys.spatialRefSys;
List<SpatialRefSys> referenceSystems = query.select(spatialRefSys).from(spatialRefSys).fetch();

2.4.5. 계승

데이터베이스 스키마에서 일반 기하학 유형만 사용하는 경우 개체 모델의 변환 방법을 사용하여 보다 구체적인 유형으로 변환할 수 있습니다.

GeometryPath<기하학> 기하학 = 모양.기하학;
PointPath<Point> point = 기하학.asPoint();
NumberExpression<Double> pointX = point.x(); // GeometryExpression/GeometryPath에서는 x()를 사용할 수 없습니다.

2.5. Lucene 쿼리 중

이 장에서는 Lucene 모듈의 쿼리 기능을 설명합니다.

2.5.1. 메이븐 통합

Querydsl Lucene은 Lucene 3의 경우 querydsl-lucene3 모듈, Lucene 4의 경우 querydsl-lucene4, Lucene 5의 경우 querydsl-lucene5를 통해 사용할 수 있습니다.

루씬 3:

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-lucene3 </artifactId> 
  <version> ${querydsl.version} </version> 
</dependent>

루씬 4:

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-lucene4 </artifactId> 
  <version> ${querydsl.version} </version> 
</dependent>

루씬 5:

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-lucene5 </artifactId> 
  <version> ${querydsl.version} </version> 
</dependent>

2.5.2. 쿼리 유형 만들기

연도 및 제목 필드를 사용하여 수동으로 생성된 쿼리 유형은 다음과 같습니다.

공개  클래스 QDocument 확장 EntityPathBase<Document> {
     private  static  final  long serialVersionUID = - 4872833626508344081L ;

    public QDocument(String var) {
         super (Document.class , PathMetadataFactory.forVariable (var));
    }

    공개  최종 StringPath year = createString( "year" );

    공개  최종 StringPath title = createString( "title" );
}

QDocument는 필드 연도와 제목이 있는 Lucene 문서를 나타냅니다.

사용 가능한 스키마 데이터가 없으므로 Lucene에서는 코드 생성을 사용할 수 없습니다.

2.5.3. 쿼리 중

Querydsl Lucene을 사용한 쿼리는 다음과 같이 간단합니다.

QDocument doc = new QDocument( "doc" );

IndexSearcher 검색자 = new IndexSearcher(index);
LuceneQuery 쿼리 = new LuceneQuery(true, 검색자);
List<Document> 문서 = 쿼리
    .where(doc.year.between( "1800" , "2000" ).and(doc.title.startsWith( "허클" ))
    .술책();

이는 다음 Lucene 쿼리로 변환됩니다.

+연도:[1800년부터 2000년까지] +제목:허클*

2.5.4. 일반적인 사용법

다음과 같이 LuceneQuery 클래스의 계단식 메소드를 사용하십시오.

여기서: 쉼표로 구분된 가변 인수 형식 또는 and 연산자를 통해 계단식으로 연결된 쿼리 필터를 추가합니다. 지원되는 작업은 match , indexOf , charAt 를 제외하고 PString에서 수행되는 작업입니다 . 현재  지원되지 않지만 향후 지원될 예정입니다.

orderBy: 결과의 순서를 순서 표현식의 varargs 배열로 추가합니다. OrderSpecifier 인스턴스에 액세스하려면 숫자, 문자열 및 기타 유사한 표현식에 asc() 및 desc()를 사용하십시오.

제한, 오프셋, 제한: 결과의 페이징을 설정합니다. 최대 결과에 대한 제한, 행 건너뛰기에 대한 오프셋 및 한 번의 호출로 둘 다를 정의하기 위한 제한.

2.5.5. 주문

순서를 선언하는 구문은 다음과 같습니다.

질문
    .where(doc.title.like( "*" ))
    .orderBy(doc.title.asc(), doc.year.desc())
    .술책();

이는 다음 Lucene 쿼리와 동일합니다.

제목:*

결과는 제목과 연도를 기준으로 오름차순으로 정렬됩니다.

또는 정렬 메서드 호출을 사용하여 대신 정렬 논리를 Sort 인스턴스로 선언할 수 있습니다.

정렬 정렬 = ...;
질문
    .where(doc.title.like( "*" ))
    .sort(정렬)
    .술책();

2.5.6. 한계

한계를 선언하는 구문은 다음과 같습니다.

질문
    .where(doc.title.like( "*" ))
    .한도( 10 )
    .술책();

2.5.7. 오프셋

오프셋을 선언하는 구문은 다음과 같습니다.

질문
    .where(doc.title.like( "*" ))
    .오프셋( 3 )
    .술책();

2.5.8. 퍼지 검색

퍼지 검색은 클래스의 fuzzyLike 메소드를 통해 표현할 수 있습니다 com.querydsl.lucene3.LuceneExpressions.

질문
    .where(LuceneExpressions.fuzzyLike(doc.title, "안녕하세요" ))
    .술책();

2.5.9. 쿼리에 Lucene 필터 적용

다음과 같이 쿼리에 단일 Lucene 필터를 적용할 수 있습니다.

질문
    .where(doc.title.like( "*" ))
    .filter(필터)
    .술책();

구별 필터링에 대한 지름길은 구별(Path) 메소드를 통해 제공됩니다:

질문
    .where(doc.title.like( "*" ))
    .distinct(문서.제목)
    .술책();

2.6. Hibernate 검색 쿼리하기

이 장에서는 Hibernate 검색 모듈의 쿼리 기능을 설명합니다.

2.6.1. Querydsl 쿼리 유형 만들기

쿼리 유형을 생성하는 방법에 대한 지침은 JPA/Hibernate 소스 쿼리를 참조하세요 .

2.6.2. 쿼리 중

Querydsl Hibernate Search를 사용한 쿼리는 다음과 같이 간단합니다.

QUser 사용자 = QUser.user;
SearchQuery<User> 쿼리 = new SearchQuery<User>(세션, 사용자);
목록<사용자> 목록 = 쿼리
    .where(user.firstName.eq( "밥" ))
    .술책();

2.6.3. 일반적인 사용법

일반적인 사용 지침은 Lucene 소스 쿼리를 참조하세요 .

쿼리 직렬화에서 Querydsl Lucene 모듈과의 유일한 차이점은 경로가 다르게 처리된다는 것입니다. 주석이 달린 속성 의 경우 org.hibernate.search.annotations.Field 이름 속성은 속성 이름과 함께 필드 이름에 대한 대체로 사용됩니다.

2.7. MongoDB 쿼리하기

이 장에서는 Mongodb 모듈의 쿼리 기능을 설명합니다.

2.7.1. 메이븐 통합

Maven 프로젝트에 다음 종속성을 추가합니다.

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-apt </artifactId> 
  <version> ${querydsl.version} </version> 
  <scope> 제공 </scope> 
</dependent>

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-mongodb </artifactId> 
  <version> ${querydsl.version} </version> 
</dependent>

이제 Querydsl에서 사용하는 쿼리 유형을 생성하는 Maven APT 플러그인을 구성합니다.

<프로젝트> 
  <빌드> 
    <플러그인>
      ...
      <plugin> 
        <groupId> com.mysema.maven </groupId> 
        <artifactId> apt-maven-plugin </artifactId> 
        <version> 1.1.3 </version> 
        <executions> 
          <execution> 
            <goals> 
              <goal> 프로세스 </goal> 
            </goals> 
            <configuration> 
              <outputDirectory> target/generated-sources/java </outputDirectory> 
              <processor> com.querydsl.apt.morphia.MorphiaAnnotationProcessor </processor> 
            </configuration> 
          </execution> 
        < /실행> </ 
      플러그인 >
    ...
    </플러그인> 
  </build> 
</project>

MorphiaAnnotationProcessor는 com.google.code.morphia.annotations.Entity 주석이 달린 도메인 유형을 찾고 이에 대한 Querydsl 쿼리 유형을 생성합니다.

새로 설치를 실행하면 쿼리 유형이 target/generated-sources/java에 생성됩니다.

Eclipse를 사용하는 경우 mvn eclipse:eclipse를 실행하여 target/generated-sources/java를 소스 폴더로 포함하도록 Eclipse 프로젝트를 업데이트하십시오.

이제 Mongodb 쿼리와 쿼리 도메인 모델의 인스턴스를 구성할 수 있습니다.

2.7.2. 쿼리 중

Morphia를 사용하여 Querydsl Mongodb로 쿼리하는 것은 다음과 같이 간단합니다.

모르피아 모르피아;
데이터스토어
// ... 
QUser user = new QUser( "사용자" );
MorphiaQuery<User> 쿼리 = new MorphiaQuery<User>(모피아, 데이터스토어, 사용자);
목록<사용자> 목록 = 쿼리
    .where(user.firstName.eq( "밥" ))
    .술책();

2.7.3. 일반적인 사용법

다음과 같이 MongodbQuery 클래스의 계단식 메소드를 사용하십시오.

여기서: 쉼표로 구분된 가변 인수 형식 또는 and 연산자를 통해 계단식으로 연결된 쿼리 필터를 추가합니다. 지원되는 작업은 match , indexOf , charAt 를 제외하고 PString에서 수행되는 작업입니다 . 현재  지원되지 않지만 향후 지원될 예정입니다.

orderBy: 결과의 순서를 순서 표현식의 varargs 배열로 추가합니다. OrderSpecifier 인스턴스에 액세스하려면 숫자, 문자열 및 기타 유사한 표현식에 asc() 및 desc()를 사용하십시오.

제한, 오프셋, 제한: 결과의 페이징을 설정합니다. 최대 결과에 대한 제한, 행 건너뛰기에 대한 오프셋 및 한 번의 호출로 둘 다를 정의하기 위한 제한.

2.7.4. 주문

순서를 선언하는 구문은 다음과 같습니다.

질문
    .where(doc.title.like( "*" ))
    .orderBy(doc.title.asc(), doc.year.desc())
    .술책();

결과는 제목과 연도를 기준으로 오름차순으로 정렬됩니다.

2.7.5. 한계

한계를 선언하는 구문은 다음과 같습니다.

질문
    .where(doc.title.like( "*" ))
    .한도( 10 )
    .술책();

2.7.6. 오프셋

오프셋을 선언하는 구문은 다음과 같습니다.

질문
    .where(doc.title.like( "*" ))
    .오프셋( 3 )
    .술책();

2.7.7. 지리공간 쿼리

지리공간 쿼리에 대한 지원은 Near-Method를 통해 Double 형식 배열(Double[])에 사용할 수 있습니다.

질문
    .where(geoEntity.location.near( 50.0 , 50.0 ))
    .술책();

2.7.8. 관련 필드만 선택

관련 필드만 선택하려면 다음과 같은 오버로드된 프로젝션 메소드인 fetch, iterate, fetchOne 및 fetchFirst 메소드를 사용할 수 있습니다.

질문
    .where(doc.title.like( "*" ))
    .fetch(doc.title, doc.path);

이 쿼리는 문서의 제목 및 경로 필드만 로드합니다.

2.8. 컬렉션 쿼리

querydsl-collections 모듈은 생성된 쿼리 유형과 함께 또는 없이 사용할 수 있습니다. 첫 번째 섹션에서는 생성된 쿼리 유형이 없는 사용법을 설명합니다.

2.8.1. 생성된 쿼리 유형이 없는 사용법

생성된 쿼리 유형 없이 querydsl-collections를 사용하려면 Querydsl 별칭 기능을 사용해야 합니다. 여기 몇 가지 예가 있어요.

시작하려면 다음 정적 가져오기를 추가하세요.

// Querydsl 컬렉션 API 액세스에 필요 
import  static com.querydsl.collections.CollQueryFactory.*;
// $-invocations를 사용하는 경우 필요합니다. 
import  static com.querydsl.core.alias.Alias.*;

이제 Cat 클래스에 대한 별칭 인스턴스를 만듭니다. 별칭 인스턴스는 빈 생성자가 있는 최종이 아닌 클래스에 대해서만 생성될 수 있습니다. 수업에 하나가 있는지 확인하십시오.

Cat 유형의 별칭 인스턴스와 해당 getter 호출은 달러 메서드 호출로 래핑하여 경로로 변환됩니다. 예를 들어 호출은 내부적으로 달러 메서드 내부의 c.getKittens() 속성 경로로 변환됩니다 .c.kittens

Cat c = alias(Cat.class , " cat" );
for (문자열 이름 : select($(c.getName())).from($(c),cats)
  .where($(c.getKittens()).size().gt( 0 ))
  .fetch()) {
    System.out.println(이름);
}

다음 예제는 목록 크기에 대한 액세스가 달러 메서드 호출 내에서 발생하는 이전 예제의 변형입니다.

Cat c = alias(Cat.class , " cat" );
for (문자열 이름 : select($(c.getName())).from($(c),cats)
  .where($(c.getKittens().size()).gt( 0 ))
  .fetch()) {
    System.out.println(이름);
}

별칭의 기본이 아닌 유형 및 최종 유형이 아닌 모든 속성은 별칭 자체입니다. 따라서 달러 메소드 범위에서 기본 유형 또는 최종이 아닌 유형(예: java.lang.String)에 도달할 때까지 메소드 호출을 계단식으로 배열할 수 있습니다.

예를 들어

$(c.getMate().getName())

내부적으로는 c.mate.name 으로 변환되지만

$(c.getMate().getName().toLowerCase())

toLowerCase() 호출이 추적되지 않으므로 제대로 변환되지 않습니다.

또한 별칭 유형에 대해서는 getter, size(), contain(Object) 및 get(int)만 호출할 수 있습니다. 다른 모든 호출에서는 예외가 발생합니다.

2.8.2. 생성된 쿼리 유형의 사용법

위의 예는 생성된 표현식 유형을 사용하여 다음과 같이 표현할 수 있습니다.

QCat cat = new QCat( "cat" );
for (문자열 이름 : select(cat.name).from(cat,cats)
  .where(cat.kittens.size().gt( 0 ))
  .fetch()) {
    System.out.println(이름);
}

생성된 쿼리 유형을 사용하는 경우 별칭 인스턴스 대신 식을 인스턴스화하고 달러 메서드 래핑 없이 속성 경로를 직접 사용합니다.

2.8.3. 메이븐 통합

Maven 프로젝트에 다음 종속성을 추가합니다.

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-apt </artifactId> 
  <version> ${querydsl.version} </version> 
  <scope> 제공 </scope> 
</dependent>

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-collections </artifactId> 
  <version> ${querydsl.version} </version> 
</dependent>

JPA 또는 JDO를 사용하지 않는 경우 주석을 추가 com.querydsl.core.annotations.QueryEntity 하고 다음 플러그인 구성을 Maven 구성(pom.xml)에 추가하여 도메인 유형에 대한 표현식 유형을 생성할 수 있습니다.

<프로젝트> 
  <빌드> 
  <플러그인>
    ...
    <plugin> 
      <groupId> com.mysema.maven </groupId> 
      <artifactId> apt-maven-plugin </artifactId> 
      <version> 1.1.3 </version> 
      <executions> 
        <execution> 
          <goals> 
            <goal> 프로세스 </goal> 
          </goals> 
          <configuration> 
            <outputDirectory> target/generated-sources/java </outputDirectory> 
            <processor> com.querydsl.apt.QuerydslAnnotationProcessor </processor> 
          </configuration> 
        </execution> 
      </executions > 
    </플러그인>
    ...
  </플러그인> 
  </build> 
</project>

2.8.4. 개미 통합

full-deps 번들의 jar 파일을 클래스 경로에 배치하고 Querydsl 코드 생성을 위해 다음 작업을 사용합니다.

    <!-- APT 기반 코드 생성 --> 
    <javac  srcdir = "${src}"  classpathref = "cp" > 
      <compilerarg  value = "-proc:only" /> 
      <compilerarg  value = "-processor" /> 
      < compilerarg  값 = "com.querydsl.apt.QuerydslAnnotationProcessor" /> 
      <compilerarg  값 = "-s" /> 
      <compilerarg  값 = "${generated}" /> 
    </javac>

    <!-- 컴파일 --> 
    <javac  classpathref = "cp"  destdir = "${build}" > 
      <src  경로 = "${src}" /> 
      <src  경로 = "${generated}" /> 
    </ javac>

src를 생성된 소스용 폴더로 생성된 기본 소스 폴더로 바꾸고 대상 폴더로 빌드합니다 .

2.8.5. 햄크레스트 매처

Querydsl 컬렉션은 Hamcrest 매처를 제공합니다. 이러한 수입품으로

 정적 org.hamcrest.core.IsEqual.equalTo 가져오기 ;
import  static com.querydsl.collections.PathMatcher.hasValue;
정적 org.junit.Assert.assertEquals 가져오기  ;
import static org.junit.Assert.assertThat;
 

다음과 같이 사용할 수 있습니다.

자동차 car = new Car();
자동차.setHorsePower( 123 );

주장그(자동차, hasValue($.horsePower));
assertThat(car, hasValue($.horsePower,equalTo( 123 )));

Hamcrest matcher는 Jeroen van Schagen 이 기여했습니다 .

2.8.6. Java용 Eclipse 컴파일러와 함께 사용

시스템 컴파일러를 사용할 수 없는 JRE에서 Querydsl 컬렉션을 사용하는 경우 대신 ECJ(Eclipse Compiler for Java)를 사용하도록 CollQuery 인스턴스를 구성할 수도 있습니다.

DefaultEvaluatorFactory evaluatorFactory = 새로운 DefaultEvaluatorFactory(
    CollQueryTemplates.DEFAULT,
    new ECJEvaluatorFactory(getClass().getClassLoader()));
QueryEngine queryEngine = new DefaultQueryEngine(evaluatorFactory);
CollQuery 쿼리 = new CollQuery(queryEngine);

2.9. 스칼라에서 쿼리하기

Scala의 Querydsl 사용에 대한 일반 지원은 querydsl-scala 모듈을 통해 제공됩니다. Maven 빌드에 추가하려면 다음 코드 조각을 사용하세요.

<종속성> 
  <groupId> com.querydsl </groupId> 
  <artifactId> querydsl-scala </artifactId> 
  <version> ${querydsl.version} </version> 
</dependent>

2.9.1. Scala용 DSL 표현식

Scala용 Querydsl은 표현식 구성을 위한 대체 DSL을 제공합니다. Scala DSL은 향상된 가독성과 간결성을 위해 연산자 오버로딩, 함수 포인터 및 암시적 가져오기와 같은 언어 기능을 활용합니다.

주요 대안에 대한 개요는 다음과 같습니다.

//표준 대안

expr isNotNull expr is not(null)
expr isNull expr은 null입니다.
expr eq "벤" expr === "벤"
expr ne "벤" expr !== "벤"
expr "X" 추가 expr + "X"
expr isEmpty expr이 비어 있습니다.
expr isNotEmpty expr이 비어 있지 않음

// 부울
왼쪽과 오른쪽 왼쪽 && 오른쪽
왼쪽 또는 오른쪽 왼쪽 || 오른쪽
expr이 아니라 !expr

// 비교
expr lt 5 expr < 5
expr loe 5 expr <= 5
expr gt 5 expr > 5
expr은 5가 됩니다. expr >= 5
expr notBetween(2,6) expr not between (2,6)
expr 부정 -expr

// 숫자
expr 3 expr + 3 추가
expr 3을 뺍니다 expr - 3
expr 나누기 3 expr / 3
expr 곱하기 3 expr * 3
expr 모드 5 expr % 5

// 수집
목록.get(0) 목록(0)
map.get("X") 맵("X")

2.9.2. SQL로 쿼리

Java용 Querydsl SQL과 마찬가지로 쿼리를 구성하려면 쿼리 유형을 생성해야 합니다. 다음 코드 예제에서는 이 작업이 수행되는 방법을 보여줍니다.

Bean 유형 없이 생성:

val 디렉토리 = 새로운 java.io.File( "target/jdbcgen1" )
val namingStrategy = 새로운 DefaultNamingStrategy()
값 내보내기 = 새 MetaDataExporter()
수출업자.setNamePrefix( "Q" )
내보내기.setPackageName( "com.querydsl" )
내보내기.setSchemaPattern( "PUBLIC" )
내보내기.setTargetFolder(디렉토리)
내보내기.setSerializerClass(classOf[ScalaMetaDataSerializer])
내보내기.setCreateScalaSources(true)
내보내기.setTypeMappings(ScalaTypeMappings.create)
수출업자.수출(connection.getMetaData)

Bean 유형을 사용한 생성:

val 디렉토리 = 새로운 java.io.File( "target/jdbcgen2" )
val namingStrategy = 새로운 DefaultNamingStrategy()
값 내보내기 = 새 MetaDataExporter()
수출업자.setNamePrefix( "Q" )
내보내기.setPackageName( "com.querydsl" )
내보내기.setSchemaPattern( "PUBLIC" )
내보내기.setTargetFolder(디렉토리)
내보내기.setSerializerClass(classOf[ScalaMetaDataSerializer])
내보내기.setBeanSerializerClass(classOf[ScalaBeanSerializer])
내보내기.setCreateScalaSources(true)
내보내기.setTypeMappings(ScalaTypeMappings.create)
수출업자.수출(connection.getMetaData)

2.9.2.1. 코드 생성

SQL 메타타입 및 프로젝션을 위한 Scala 소스는 ​​querydsl-maven-plugin을 사용하여 생성할 수 있습니다. 다음은 구성 예입니다.

<프로젝트> 
  <빌드> 
    <플러그인>
      ...
      <plugin> 
        <groupId> com.querydsl </groupId> 
        <artifactId> querydsl-maven-plugin </artifactId> 
        <version> ${querydsl.version} </version> 
        <configuration> 
          <jdbcDriver> com.mysql.jdbc. 드라이버 </jdbcDriver> 
          <jdbcUrl> jdbc:mysql://localhost:3306/test </jdbcUrl> 
          <jdbcUser> matko </jdbcUser> 
          <jdbcPassword> matko </jdbcPassword> 
          <packageName> com.example.schema </packageName > 
          <targetFolder> ${project.basedir}/src/main/scala </targetFolder> 
          <exportBeans> true </exportBeans> 
          <createScalaSources> true </createScalaSources> 
        </configuration> 
        <종속성> 
          <종속성> 
            <groupId> mysql </groupId> 
            <artifactId> mysql-connector-java </artifactId> 
            <version> 5.1.16 </version> 
          </dependent> 
          <dependent> 
            <groupId> com.querydsl </groupId> 
            <artifactId> querydsl-scala < /artifactId> 
            <version> ${querydsl.version} </version> 
          </dependent> 
          <dependent> 
            <groupId> org.scala-lang </groupId> 
            <artifactId> scala-library </artifactId> 
            <version> ${ scala.version} </version> 
          </dependent> 
        </dependent> 
      </plugin>
      ...
    </플러그인> 
  </build> 
</project>

실행할 Maven 목표는 querydsl:export입니다.

2.9.3. 다른 백엔드로 쿼리

다른 백엔드로 쿼리하는 경우 표현식 모델을 수동으로 생성해야 하거나 별칭 기능을 사용할 수 있습니다.

다음은 JPA를 사용한 최소한의 예입니다.

@Entity
 클래스 사용자 {
   @BeanProperty 
  @Id
  변수 ID: 정수 = _;
  @BeanProperty
  var 사용자 이름: 문자열 = _;
  @BeanProperty 
  @ManyToOne
  var 부서: 부서 = _;
}

@Entity
 클래스 부서 {
   @BeanProperty 
  @Id
  변수 ID: 정수 = _;
  @BeanProperty
  변수 이름: 문자열 = _;
}

다음은 몇 가지 쿼리 예입니다.

목록

val person = "사람" 으로서의 사람

selectFrom(person).where(person.firstName like "Rob%" ).fetch()

고유한 결과

selectFrom(person).where(person.firstName like "Rob%" ).fetchOne()

긴 곳

선택(사람)
  .where(person.firstName like "Rob%" , person.lastName like "An%" )
  .술책()

주문하다

selectFrom(사람).orderBy(person.firstName asc).fetch()

null이 아님

선택(사람)
  .where(person.firstName isEmpty, person.lastName isNotNull)
  .술책()

쿼리 생성을 위한 팩토리 메서드는 다음과 같습니다.

def 쿼리() = 새로운 JPAQuery(entityManager)

쿼리 외에도 다음과 같이 생성할 수 있는 변수가 필요합니다.

val person = "사람" 으로서의 사람

참고: XML 기반 구성으로 Hibernate를 사용하는 경우 Scala 지원은 아직 사용할 수 없습니다. HibernateDomainExporter는 현재 Java 소스 파일만 출력합니다.

3. 일반적인 사용법

일반 사용법 섹션에서는 참조 문서의 튜토리얼 섹션에서 다루지 않은 측면을 다룹니다. 유스케이스 중심의 구조를 따릅니다.

3.1. 쿼리 만들기

Querydsl의 쿼리 구성에는 표현식 인수를 사용하여 쿼리 메서드를 호출하는 작업이 포함됩니다. 쿼리 메서드는 대부분 모듈별로 다르며 이미 튜토리얼 섹션에 제시되어 있으므로 이 부분에서는 표현식에 중점을 둘 것입니다.

표현식은 일반적으로 도메인 모듈의 생성된 표현식 유형에서 필드에 액세스하고 메소드를 호출하여 구성됩니다. 코드 생성을 적용할 수 없는 경우 표현식을 구성하는 일반적인 방법을 대신 사용할 수 있습니다.

3.1.1. 복잡한 술어

복잡한 부울 표현식을 구성하려면 com.querydsl.core.BooleanBuilder클래스를 사용하십시오. Predicate를 구현하고 계단식 형식으로 사용할 수 있습니다.

public List<Customer> getCustomer(String... names) {
    QCustomer 고객 = QCustomer.customer;
    JPAQuery<고객> 쿼리 = queryFactory.selectFrom(고객);
    BooleanBuilder 빌더 = new BooleanBuilder();
    for (문자열 이름 : 이름) {
        builder.or(고객.이름.eq(이름));
    }
    query.where(빌더); // 고객.이름 eq 이름1 OR 고객.이름 eq 이름2 OR ... 
    return query.fetch();
}

BooleanBuilder변경 가능하며 처음에는 null을 나타내고 각각 이후에는 and 또는 or작업 결과를 호출합니다.

3.1.2. 동적 표현

클래스 com.querydsl.core.types.dsl.Expressions 는 동적 표현식 구성을 위한 정적 팩토리 클래스입니다. 팩토리 메소드는 반환된 유형에 따라 이름이 지정되며 대부분 자체 문서화됩니다.

일반적으로 Expressions클래스는 동적 경로, 사용자 정의 구문 또는 사용자 정의 작업과 같이 유연한 DSL 형식을 사용할 수 없는 경우에만 사용해야 합니다.

다음 표현식

QPerson 사람 = QPerson.person;
person.firstName.startsWith( "P" );

Q 유형을 사용할 수 없으면 이와 같이 구성할 수 있습니다.

Path<Person> person = Expressions.path(Person.class , " person" );
Path<String> personFirstName = Expressions.path(String.class , person, "firstName" );
Constant<String> 상수 = Expressions.constant( "P" );
Expressions.predicate(Ops.STARTS_WITH, personFirstName, 상수);

Path 인스턴스는 변수와 속성을 나타내고, Constants는 상수, Operations는 연산을 나타내며, TemplateExpression 인스턴스는 표현식을 문자열 템플릿으로 표현하는 데 사용할 수 있습니다.

3.1.3. 동적 경로

기반 표현식 생성 외에도 ExpressionsQuerydsl은 동적 경로 생성을 위한 보다 유연한 API를 제공합니다.

동적 경로 생성을 위해 com.querydsl.core.types.dsl.PathBuilder클래스를 사용할 수 있습니다. 이는 EntityPathBase클래스 생성 및 경로 생성을 위한 별칭 사용에 대한 대안으로 확장되어 사용될 수 있습니다.

Expressions API와 비교하여 PathBuilder는 알 수 없는 작업이나 사용자 정의 구문에 대한 직접적인 지원을 제공하지 않지만 구문은 일반 DSL에 더 가깝습니다.

문자열 속성:

PathBuilder<User> 엔터티Path = new 
PathBuilder<User>(User.class , " entity" );
// 완전 일반 액세스 
entityPath.get( "userName" );
// .. 또는 제공된 유형을 사용하여 
entityPath.get( "userName" , String.class );
// .. 그리고 올바른 서명 
entityPath.getString( "userName" ).lower();

구성 요소 유형이 포함된 목록 속성:

entityPath.getList( " list" , String.class ).get( 0 );

구성요소 표현식 유형 사용:

entityPath.getList( "list" , String.class , StringPath.class ).get( 0 ).lower ( );

키와 값 유형이 있는 맵 속성:

entityPath.getMap( "map" , String.class , String.class ) .get( " key" );

구성요소 표현식 유형 사용:

entityPath.getMap( "map" , String.class , String.class , StringPath.class ) .get( "key" ) .lower()
 ;

PathBuilder 유효성 검사를 위해 PathBuilderValidator를 사용할 수 있습니다. 생성자에 주입될 수 있으며 새 PathBuilder에 대해 전이적으로 사용됩니다.

PathBuilder<Customer> 고객 = new PathBuilder<Customer>(Customer.class , " customer" , 유효성 검사기);

PathBuilderValidator.FIELDS는 필드 존재를 확인하고, PathBuilderValidator.PROPERTIES는 Bean 속성의 유효성을 검사하며, JPAPathBuilderValidator는 JPA 메타모델을 사용하여 유효성을 검사합니다.

3.1.4. 사례 표현

Case-When-Then-Else 표현식을 구성하려면 CaseBuilder다음과 같은 클래스를 사용하십시오.

QCustomer 고객 = QCustomer.customer;
Expression<String> 케이스 = 새 CaseBuilder()
    .when(customer.annualSpending.gt( 10000 )).then( "프리미어" )
    .when(customer.annualSpending.gt( 5000 )).then( "골드" )
    .when(customer.annualSpending.gt( 2000 )).then( "실버" )
    .그렇지 않으면( "청동" );
// 이제 Cases 표현식을 프로젝션이나 조건에서 사용할 수 있습니다.

등호 연산이 포함된 사례 표현식의 경우 다음과 같은 간단한 형식을 대신 사용하세요.

QCustomer 고객 = QCustomer.customer;
표현식<문자열> 사례 = customer.annualSpending
    .when( 10000 ).then( "프리미어" )
    .when( 5000 ).then( "골드" )
    .when( 2000 ).then( "실버" )
    .그렇지 않으면( "청동" );
// 이제 Cases 표현식을 프로젝션이나 조건에서 사용할 수 있습니다.

Case 표현식은 아직 JDOQL에서 지원되지 않습니다.

3.1.5. 캐스팅 표현

표현식 유형의 일반 서명을 방지하기 위해 유형 계층이 평면화됩니다. 결과적으로 생성된 모든 쿼리 유형은 com.querydsl.core.types.dsl.EntityPathBase 또는 의 직접적인 하위 클래스 com.querydsl.core.types.dsl.BeanPath 이며 논리적 상위 유형으로 직접 캐스트될 수 없습니다.

직접적인 Java 캐스트 대신 _super필드를 통해 상위 유형 참조에 액세스할 수 있습니다. _super-field는 단일 상위 유형으로 생성된 모든 쿼리 유형에서 사용할 수 있습니다.

// 계정 
QAccount 에서 EntityPathBase<Account>를
     확장합니다. { // ...
}

// BankAccount에서 Account 확장 
QBankAccount 확장 EntityPathBase<BankAccount> {

    공개  최종 QAccount _super = 새 QAccount( this );

    // ...
}

상위 유형에서 하위 유형으로 변환하려면 EntityPathBase 클래스의 as-메서드를 사용할 수 있습니다.

QAccount 계정 = 새 QAccount( "계정" );
QBankAccountbankAccount = account.as(QBankAccount.class ) ;

3.1.6. 리터럴 선택

리터럴은 상수 표현식을 통해 참조하여 선택할 수 있습니다. 다음은 간단한 예입니다.

query.select(Expressions.constant( 1 ),
             Expressions.constant( "abc" ));

상수 표현식은 하위 쿼리에 자주 사용됩니다.

3.2. 결과 처리

Querydsl은 결과를 사용자 정의하는 두 가지 방법, 즉 행 기반 변환을 위한 FactoryExpressions와 집계를 위한 ResultTransformer를 제공합니다.

인터페이스 com.querydsl.core.types.FactoryExpression는 Bean 생성, 생성자 호출 및 보다 복잡한 객체 생성에 사용됩니다. Querydsl의 FactoryExpression 구현 기능은 com.querydsl.core.types.Projections클래스를 통해 액세스할 수 있습니다.

com.querydsl.core.ResultTransformer인터페이스 의 경우 GroupBy주요 구현입니다.

3.2.1. 여러 열 반환

Querydsl 3.0부터 다중 열 결과의 기본 유형은 입니다 com.querydsl.core.Tuple. Tuple은 Tuple 행 객체의 열 데이터에 액세스하기 위한 인터페이스와 같은 형식이 안전한 Map을 제공합니다.

List<Tuple> 결과 = query.select(employee.firstName, Employee.firstName)
                          .from(직원).fetch();
for (튜플 행 : 결과) {
     System.out.println( "firstName " + row.get(employee.firstName));
     System.out.println( "lastName " + row.get(employee.lastName));
}}

이 예는 다음과 같이 QTuple 표현식 클래스를 통해 작성될 수도 있습니다.

List<Tuple> 결과 = query.select( new QTuple(employee.firstName, Employee.firstName))
                          .from(직원).fetch();
for (튜플 행 : 결과) {
     System.out.println( "firstName " + row.get(employee.firstName));
     System.out.println( "lastName " + row.get(employee.lastName));
}}

3.2.2. 콩 개체수

쿼리 결과에 따라 Bean을 채워야 하는 경우 Bean 프로젝션을 다음과 같이 사용할 수 있습니다.

List<UserDTO> dtos = query.select(
    Projections.bean(UserDTO.class , user.firstName, user.lastName)).fetch();

setter 대신 필드를 직접 사용해야 하는 경우 다음 변형을 대신 사용할 수 있습니다.

List<UserDTO> dtos = query.select(
    Projections.fields(UserDTO.class , user.firstName, user.lastName)).fetch();

3.2.3. 생성자 사용법

생성자 기반 행 변환은 다음과 같이 사용할 수 있습니다.

List<UserDTO> dtos = query.select(
    Projections.constructor(UserDTO.class , user.firstName, user.lastName)).fetch();

일반 생성자 표현식 사용법 대신 생성자에 주석을 달 수도 있습니다 QueryProjection.

클래스 CustomerDTO {

  @QueryProjection
   public CustomerDTO( 긴 id, 문자열 이름) {
     ...
  }

}

그런 다음 쿼리에서 다음과 같이 사용할 수 있습니다.

QCustomer 고객 = QCustomer.customer;
JPQLQuery 쿼리 = new HibernateQuery(세션);
List<CustomerDTO> dtos = query.select( new QCustomerDTO(customer.id, customer.name))
                              .from(고객).fetch();

예제는 Hibernate에 특정하지만 이 기능은 모든 모듈에서 사용 가능합니다.

QueryProjection 주석이 있는 유형이 주석이 달린 엔터티 유형이 아닌 경우 예제와 같이 생성자 프로젝션을 사용할 수 있지만 주석이 달린 유형이 엔터티 유형인 경우 생성자 프로젝션은 다음 호출을 통해 생성되어야 합니다. 쿼리 유형의 정적 생성 메소드:

@Entity
 클래스 고객 {

  @QueryProjection
   public Customer( 긴 id, 문자열 이름) {
     ...
  }

}
QCustomer 고객 = QCustomer.customer;
JPQLQuery 쿼리 = new HibernateQuery(세션);
List<고객> dtos = query.select(QCustomer.create(customer.id, customer.name))
                           .from(고객).fetch();

또는 코드 생성이 옵션이 아닌 경우 다음과 같이 생성자 프로젝션을 만들 수 있습니다.

List<고객> dtos = 쿼리
    .select(Projections.constructor(Customer.class , customer.id, customer.name))
    .from(고객).fetch();

3.2.4. 결과 집계

클래스 com.querydsl.core.group.GroupBy 는 쿼리 결과를 메모리에 집계하는 데 사용할 수 있는 집계 기능을 제공합니다. 다음은 몇 가지 사용 예입니다.

상위 하위 관계 집계

import  static com.querydsl.core.group.GroupBy.*;

Map<Integer, List<Comment>> 결과 = query.from(게시물, 댓글)
    .where(comment.post.id.eq(post.id))
    .transform(groupBy(post.id).as(list(comment)));

그러면 관련 댓글에 대한 게시물 ID 맵이 반환됩니다.

여러 결과 열

Map<Integer, Group> 결과 = query.from(게시물, 댓글)
    .where(comment.post.id.eq(post.id))
    .transform(groupBy(post.id).as(post.name, set(comment.id)));

그러면 게시물 이름과 댓글 ID에 액세스할 수 있는 그룹 인스턴스에 게시물 ID 맵이 반환됩니다.

Group은 Tuple 인터페이스와 동등한 GroupBy입니다.

더 많은 예는 여기에서 찾을 수 있습니다 .

3.3. 코드 생성

Java 6 APT 주석 처리 기능은 JPA, JDO 및 Mongodb 모듈의 코드 생성을 위해 Querydsl에서 사용됩니다. 이 섹션에서는 코드 생성을 위한 다양한 구성 옵션과 APT 사용에 대한 대안을 설명합니다.

3.3.1. 경로 초기화

기본적으로 Querydsl은 처음 두 수준의 참조 속성만 초기화합니다. 더 긴 초기화 경로가 필요한 경우 com.querydsl.core.annotations.QueryInit 주석을 통해 도메인 유형에 주석을 달아야 합니다. QueryInit은 깊은 초기화가 필요한 속성에 사용됩니다. 다음 예에서는 사용법을 보여줍니다.

@Entity
 클래스 이벤트 {
     @QueryInit("customer.address")
    계정 계정;
}

@Entity
 클래스 계정 {
    고객 고객;
}

@Entity
 클래스 고객 {
    문자열 이름;
    주소 주소;
    // ...
}

이 예에서는 이벤트 경로가 루트 경로/변수로 초기화될 때 account.customer 경로의 초기화를 시행합니다. 경로 초기화 형식은 "customer.*" 또는 "*"와 같은 와일드카드도 지원합니다.

자동 경로 초기화는 엔터티 필드가 최종이 아니어야 했던 수동 경로 초기화를 대체합니다. 선언적 형식은 쿼리 유형의 모든 최상위 인스턴스에 적용되고 최종 엔터티 필드를 사용할 수 있다는 이점이 있습니다.

자동 경로 초기화는 선호되는 초기화 전략이지만 수동 초기화는 아래 설명된 Config 주석을 통해 활성화할 수 있습니다.

3.3.2. 맞춤화

Querydsl의 직렬화는 패키지 및 유형에 대한 Config 주석을 통해 사용자 정의할 수 있습니다. 주석이 달린 패키지 또는 유형의 직렬화를 사용자 정의합니다.

직렬화 옵션은 다음과 같습니다.

표 3.1. 구성 옵션

이름설명
엔터티접근자 공개 최종 필드 대신 엔터티 경로에 대한 접근자 메서드(기본값: false)
목록접속자 listProperty(int index) 스타일 메소드(기본값: false)
지도접근자 mapProperty(Key key) 스타일 접근자 메서드(기본값: false)
createDefault변수 기본 변수 생성 (기본값: true)
기본변수이름 기본 변수의 이름

다음은 몇 가지 예입니다.

엔터티 유형 직렬화 사용자 정의:

@Config(entityAccessors=true) 
@Entity
 공용  클래스 사용자 {
     //...
}

패키지 콘텐츠 맞춤화:

@Config(listAccessors=true)
 패키지 com.querydsl.core.domain.rel;

import com.querydsl.core.annotations.Config;

직렬 변환기 구성을 전역적으로 사용자 정의하려면 다음 APT 옵션을 통해 이를 수행할 수 있습니다.

표 3.2. APT 옵션

이름설명
querydsl.entity접근자 참조 필드 접근자를 활성화합니다.
querydsl.list접근자 직접 인덱싱된 목록 액세스를 위해 접근자를 활성화합니다.
querydsl.map접근자 직접 키 기반 맵 액세스를 위한 접근자를 활성화합니다.
querydsl.prefix 쿼리 유형의 접두사 재정의(기본값: Q)
querydsl.suffix 쿼리 유형에 대한 접미사 설정
querydsl.packageSuffix 쿼리 유형 패키지에 대한 접미사 설정
querydsl.createDefaultVariable 기본 변수 생성 여부 설정
querydsl.unknownAsEmbeddable 주석이 달린 알 수 없는 클래스를 삽입 가능한 것으로 처리해야 하는 위치를 설정합니다(기본값: false).
querydsl.includedPackages 코드 생성에 포함될 쉼표로 구분된 패키지 목록(기본값: all)
querydsl.includedClasses 코드 생성에 포함될 클래스 이름의 쉼표로 구분된 목록(기본값: all)
querydsl.excludedPackages 코드 생성에서 제외할 쉼표로 구분된 패키지 목록(기본값: 없음)
querydsl.excludedClasses 코드 생성에서 제외할 클래스 이름을 쉼표로 구분한 목록(기본값: 없음)
querydsl.useFields 필드를 메타데이터 소스로 사용할지 여부 설정(기본값: true)
querydsl.useGetters 접근자를 메타데이터 소스로 사용할지 여부 설정(기본값: true)
querydsl.generatedAnnotationClass 생성된 소스에 추가할 단일 요소 주석 (문자열 요소 포함) 의 정규화된 클래스 이름입니다 . com.querydsl.core.annotations.Generated 에 빌드하면 Jacoco와 같은 바이트 코드 분석 도구에 사용할 수 있는 CLASS 보존 기능이 있습니다. (기본값: Java 버전에 따라 javax.annotation.Generated 또는 javax.annotation.processing.Generated ). 단일 요소 주석 도 참조하세요.

Maven APT 플러그인을 사용하면 다음과 같이 작동합니다.

<프로젝트> 
  <빌드> 
  <플러그인>
    ...
    <plugin> 
      <groupId> com.mysema.maven </groupId> 
      <artifactId> apt-maven-plugin </artifactId> 
      <version> 1.1.3 </version> 
      <executions> 
        <execution> 
          <goals> 
            <goal> 프로세스 </goal> 
          </goals> 
          <configuration> 
            <outputDirectory> target/generated-sources/java </outputDirectory> 
            <processor> com.querydsl.apt.jpa.JPAAnnotationProcessor </processor> 
            <options> 
              <querydsl.entityAccessors> true </querydsl.entityAccessors> 
              <querydsl.useFields> false </querydsl.useFields> 
            </options> 
          </configuration> 
        </execution> 
      </executions> 
    </plugin>
    ...
  </플러그인> 
  </build> 
</project>

또는 maven-compiler-pluginAPT를 컴파일에 직접 연결하도록 구성할 수도 있습니다.

      <프로젝트> 
        <빌드> 
        <플러그인>
          ...
          <plugin> 
            <artifactId> maven-compiler-plugin </artifactId> 
            <configuration> 
              <generatedSourcesDirectory> target/generated-sources/java </generatedSourcesDirectory> 
              <compilerArgs> 
                <arg> -Aquerydsl.entityAccessors=true </arg> 
                <arg > -Aquerydsl.useFields=false </arg> 
              </compilerArgs> 
            </configuration> 
            <종속성> < 
              종속성> 
                <groupId> com.querydsl </groupId> 
                <artifactId> querydsl-apt </artifactId> 
                <version> ${ querydsl.version} </version> 
                <classifier> jpa </classifier> 
              </dependent> 
              <dependent> 
                <groupId> org.hibernate.javax.persistence </groupId> 
                <artifactId> hibernate-jpa-2.1-api </artifactId > 
                <version> 1.0.0.최종 </version> 
              </dependent> 
            </dependent> 
          </plugin>
          ...
        </플러그인> 
        </build> 
      </project>

에 대한 종속성을 정의할 때 적절한 분류자를 사용해야 합니다 com.querydsl:querydsl-apt. 이러한 추가 아티팩트는 에서 사용할 주석 프로세서를 정의합니다 META-INF/services/javax.annotation.processing.Processor.

사용 가능한 분류자는 다음과 같습니다.

  • general
  • hibernate
  • jdo
  • jpa

이 구성을 사용하면 쿼리 개체는 도메인 개체를 컴파일하는 동안 소스를 생성하고 컴파일할 수 있습니다. 그러면 생성된 소스 디렉터리가 Maven 프로젝트 소스 루트에 자동으로 추가됩니다.

이 접근 방식의 가장 큰 장점은 groovy-eclipse컴파일러를 사용하여 주석이 달린 Groovy 클래스도 처리할 수 있다는 것입니다.

      <프로젝트> 
        <빌드> 
        <플러그인>
          ...
          <plugin> 
            <artifactId> maven-compiler-plugin </artifactId> 
            <configuration> 
              <compilerId> groovy-eclipse-compiler </compilerId> 
              <generatedSourcesDirectory> target/generated-sources/java </generatedSourcesDirectory> 
              <compilerArgs> 
                <arg> -Aquerydsl.entityAccessors=true </arg> 
                <arg> -Aquerydsl.useFields=false </arg> 
              </compilerArgs> 
            </configuration> 
            <종속성> 
              <종속성> 
                <groupId> org.codehaus.groovy </groupId> 
                < ArtifactId> groovy-eclipse-compiler </artifactId> 
                <version> 2.9.1-01 </version> 
              </dependent> 
              <dependent> 
                <groupId> org.codehaus.groovy </groupId> 
                <artifactId> groovy-eclipse-batch </artifactId> 
                <version> 2.3.7-01 </version> 
              </dependent> 
              <dependent> 
                <groupId> com.querydsl </groupId> 
                <artifactId> querydsl-apt </artifactId> 
                <version> ${querydsl. 버전} </version> 
                <classifier> jpa </classifier> 
              </dependent> 
              <dependent> 
                <groupId> org.hibernate.javax.persistence </groupId> 
                <artifactId> hibernate-jpa-2.1-api </artifactId> 
                < 버전> 1.0.0.최종 </version> 
              </dependent> 
            </dependent> 
          </plugin>
          ...
        </플러그인> 
        </build> 
      </project>

3.3.3. 사용자 정의 유형 매핑

사용자 정의 유형 매핑을 속성에 사용하여 파생된 경로 유형을 재정의할 수 있습니다. 이는 특정 문자열 경로에서 비교 및 ​​문자열 작업을 차단해야 하거나 사용자 정의 유형에 대한 날짜/시간 지원을 추가해야 하는 경우에 유용할 수 있습니다. Joda 시간 API 및 JDK(java.util.Date, 달력 및 하위 유형)의 날짜/시간 유형에 대한 지원이 내장되어 있지만 이 기능을 사용하여 다른 API를 지원해야 할 수도 있습니다.

다음 예에서는 사용법을 보여줍니다.

@Entity
 공용  클래스 MyEntity {
     @QueryType(PropertyType.SIMPLE)
     공용 문자열 stringAsSimple;

    @QueryType(PropertyType.COMPARABLE)
     공용 문자열 stringAsComparable;

    @QueryType(PropertyType.NONE)
     공개 문자열 stringNotInQuerydsl;
}

이 값은 PropertyType.NONE쿼리 유형 생성 시 속성을 건너뛰는 데 사용될 수 있습니다. 이 경우는 속성이 유지되지 않는 @Transient 또는 @QueryTransient 주석이 달린 속성과 다릅니다. PropertyType.NONE은 Querydsl 쿼리 유형에서 속성을 생략합니다.

3.3.4. 위임 방법

정적 메서드를 대리자 메서드로 선언하려면 해당 도메인 유형을 값으로 사용하여 QueryDelegate 주석을 추가하고 해당 Querydsl 쿼리 유형을 첫 번째 인수로 사용하는 메서드 시그니처를 제공하세요.

다음은 단위 테스트의 간단한 예입니다.

@QueryEntity
 공용  정적  클래스 사용자 {

    문자열 이름;

    사용자 관리자;

}
@QueryDelegate(User.class)
 public  static BooleanPath isManagedBy(QUser user, User other) {
     return user.manager.eq(other);
}

그리고 QUser 쿼리 유형에서 생성된 메소드는 다음과 같습니다.

public BooleanPath isManagedBy(QUser other) {
     return DelegateTest.isManagedBy( this , other);
}

대리자 메서드를 사용하여 내장 유형을 확장할 수도 있습니다. 여기 몇 가지 예가 있어요

공개  클래스 QueryExtensions {

    @QueryDelegate(Date.class)
     public  static BooleanExpression inPeriod(DatePath<Date> 날짜, 쌍<Date,Date> 기간) {
         return date.goe(기간.getFirst()).and(date.loe(기간.getSecond() )));
    }

    @QueryDelegate(Timestamp.class)
     public  static BooleanExpression inDatePeriod(DateTimePath<Timestamp> 타임스탬프, 쌍<Date,Date> 기간) {
        타임스탬프 우선 = new Timestamp(DateUtils.truncate(기간.getFirst(), Calendar.DAY_OF_MONTH).getTime());
        달력 두 번째 = Calendar.getInstance();
        second.setTime(DateUtils.truncate(기간.getSecond(), Calendar.DAY_OF_MONTH));
        second.add( 1 , Calendar.DAY_OF_MONTH);
        return timestamp.goe(first).and(timestamp.lt( new Timestamp(second.getTimeInMillis())));
    }

}

내장 유형에 대해 대리자 메서드가 선언되면 적절한 대리자 메서드 사용이 포함된 하위 클래스가 생성됩니다.

공개  클래스 QDate는 DatePath<java.sql.Date> {를 확장합니다.

    public QDate(BeanPath<? 확장 java.sql.Date> 엔터티) {
         super (entity.getType(), 엔터티.getMetadata());
    }

    public QDate(PathMetadata<?> 메타데이터) {
         super (java.sql.Date.class , 메타데이터);
    }

    public BooleanExpression inPeriod(com.mysema.commons.lang.Pair<java.sql.Date, java.sql.Date> period) {
         return QueryExtensions.inPeriod( this , period);
    }

}

공개  클래스 QTimestamp는 DateTimePath<java.sql.Timestamp> {를 확장합니다.

    공개 QTimestamp(BeanPath<? 확장 java.sql.Timestamp> 엔터티) {
         super (entity.getType(), 엔터티.getMetadata());
    }

    공개 QTimestamp(PathMetadata<?> 메타데이터) {
         super (java.sql.Timestamp.class , 메타데이터);
    }

    public BooleanExpression inDatePeriod(com.mysema.commons.lang.Pair<java.sql.Date, java.sql.Date> period) {
         return QueryExtensions.inDatePeriod( this , period);
    }

}

3.3.5. 주석이 없는 유형

주석을 생성하여 주석이 없는 유형에 대한 Querydsl 쿼리 유형을 생성할 수 있습니다 @QueryEntities. 선택한 패키지에 QueryEntities 주석을 배치하고 value 속성에 미러링할 클래스를 배치하기만 하면 됩니다.

실제로 유형을 생성하려면 com.querydsl.apt.QuerydslAnnotationProcessor. Maven에서는 다음과 같이 합니다.

<프로젝트> 
  <빌드> 
  <플러그인>
    ...
    <plugin> 
      <groupId> com.mysema.maven </groupId> 
      <artifactId> apt-maven-plugin </artifactId> 
      <version> 1.1.3 </version> 
      <executions> 
        <execution> 
          <goals> 
            <goal> 프로세스 </goal> 
          </goals> 
          <configuration> 
            <outputDirectory> target/generated-sources/java </outputDirectory> 
            <processor> com.querydsl.apt.QuerydslAnnotationProcessor </processor> 
          </configuration> 
        </execution> 
      </executions > 
    </플러그인>
    ...
  </플러그인> 
  </build> 
</project>

3.3.6. 클래스 경로 기반 코드 생성

Scala 또는 Groovy와 같은 다른 JVM 언어를 사용하거나 바이트코드 조작을 통한 주석 추가와 같이 주석이 달린 Java 소스를 사용할 수 없는 경우 클래스를 사용하여 주석이 GenericExporter달린 클래스에 대한 클래스 경로를 스캔하고 이에 대한 쿼리 유형을 생성할 수 있습니다.

GenericExporter를 사용 가능하게 하려면 프로젝트의 querydsl-codegen 모듈에 대한 종속성을 추가하거나 더 정확하게는 com.querydsl:querydsl-codegen:${querydsl.version}.

아래는 JPA의 예입니다.

GenericExporter 내보내기 = new GenericExporter();
importer.setKeywords(Keywords.JPA);
importer.setEntityAnnotation(Entity.class ) ;
importer.setEmbeddableAnnotation(Embeddable.class ) ;
importer.setEmbeddedAnnotation(Embedded.class ) ;
importer.setSupertypeAnnotation(MappedSuperclass.class ) ;
importer.setSkipAnnotation(Transient.class ) ;
importer.setTargetFolder( new File( "target/generated-sources/java" ));
importer.export(DomainClass.class .getPackage ());

그러면 DomainClass 클래스 패키지와 하위 패키지에 있는 모든 JPA 주석이 달린 클래스가 target/generated-sources/java 디렉터리로 내보내집니다.

3.3.6.1. Maven을 통한 사용법

querydsl-maven-plugin의 generic-export, jpa-export 및 jdo-export 목표는 Maven을 통한 GenericExporter 사용에 사용될 수 있습니다.

다양한 목표는 Querydsl, JPA 및 JDO 주석에 매핑됩니다.

구성 요소는 다음과 같습니다.

표 3.3. 메이븐 구성

유형요소설명
파일 대상폴더 생성된 소스의 대상 폴더
부울 스칼라 대신 Scala 소스를 생성해야 하는 경우 true(기본값: false)
끈[] 패키지 엔터티 클래스를 검사할 패키지
부울 핸들필드 true, 필드를 속성으로 처리해야 하는 경우(기본값: true)
부울 핸들메서드 true, getter가 속성으로 처리되어야 하는 경우(기본값: true)
소스인코딩 생성된 소스 파일의 문자 세트 인코딩
부울 테스트클래스 경로 true, 테스트 클래스 경로를 대신 사용해야 하는 경우

다음은 JPA 주석이 달린 클래스의 예입니다.

<프로젝트> 
  <빌드> 
    <플러그인>
      ...
      <plugin> 
        <groupId> com.querydsl </groupId> 
        <artifactId> querydsl-maven-plugin </artifactId> 
        <version> ${querydsl.version} </version> 
        <executions> 
          <execution> 
            <phase> 프로세스 클래스 </phase> 
            <goals> 
              <goal> jpa-export </goal> 
            </goals> 
            <configuration> 
              <targetFolder> target/generated-sources/java </targetFolder> 
              <packages> 
                <package> com.example.domain < /package> 
              </packages> 
            </configuration> 
          </execution> 
        </executions> 
      </plugin>
      ...
    </플러그인> 
  </build> 
</project>

com.example.domain그러면 패키지 및 하위 패키지의 JPA 주석이 달린 클래스가 target/generated-sources/java 디렉토리로 내보내집니다 .

그 이후에 생성된 소스를 직접 컴파일해야 하는 경우 compile해당 목표를 사용할 수 있습니다.

<execution> 
  <goals> 
    <goal> 컴파일 </goal> 
  </goals> 
  <configuration> 
    <sourceFolder> target/generated-sources/scala </targetFolder> 
  </configuration> 
</execution>

목표 compile에는 다음과 같은 구성 요소가 있습니다.

표 3.4. 메이븐 구성

유형요소설명
파일 소스폴더 생성된 소스가 있는 소스 폴더
소스인코딩 소스의 문자셋 인코딩
원천 -컴파일러의 소스 옵션
표적 -컴파일러의 대상 옵션
부울 테스트클래스 경로 true, 테스트 클래스 경로를 대신 사용해야 하는 경우
지도 컴파일러옵션 컴파일러 옵션

제외한 모든 옵션은 sourceFolder선택사항입니다.

3.3.6.2. 스칼라 지원

클래스의 Scala 출력이 필요한 경우 다음 구성의 변형을 사용하십시오.

<프로젝트> 
  <빌드> 
    <플러그인>
      ...
      <plugin> 
        <groupId> com.querydsl </groupId> 
        <artifactId> querydsl-maven-plugin </artifactId> 
        <version> ${querydsl.version} </version> 
        <종속성 
          > <종속성> 
            <groupId> com.querydsl </groupId> 
            <artifactId> querydsl-scala </artifactId> 
            <version> ${querydsl.version} </version> 
          </dependent> 
          <dependent> 
            <groupId> org.scala-lang </groupId> 
            <artifactId> scala -library </artifactId> 
            <version> ${scala.version} </version> 
          </dependent> 
        </dependent> 
        <executions> 
          <execution> 
            <goals> 
              <goal> jpa-export </goal> 
            </goals> 
            <configuration> 
              <targetFolder> target/generated-sources/scala </targetFolder> 
              <scala> true </scala> 
              <packages> 
                <package> com.example.domain </package> 
              </packages> 
            </configuration> 
          </ 실행> 
        </실행 
      > </플러그인>
      ...
    </플러그인> 
  </build> 
</project>

3.4. 별칭 사용

코드 생성이 옵션이 아닌 경우 별칭 개체를 식 구성을 위한 경로 참조로 사용할 수 있습니다. getter 메소드 호출을 통해 프록시된 Java Bean 객체를 통해 사용할 수 있습니다.

다음 예에서는 생성된 유형을 기반으로 식 생성을 위한 대체 항목으로 별칭 개체를 사용할 수 있는 방법을 보여줍니다.

먼저 APT 생성 도메인 유형을 사용한 예제 쿼리는 다음과 같습니다.

QCat cat = new QCat( "cat" );
for (문자열 이름 : queryFactory.select(cat.name).from(cat,cats)
    .where(cat.kittens.size().gt( 0 ))
    .fetch()) {
    System.out.println(이름);
}

이제 Cat 클래스에 대한 별칭 인스턴스가 있습니다. c.getKittens()달러 메서드 내부의 호출은 내부적으로 속성 경로로 변환됩니다 c.kittens.

Cat c = alias(Cat.class , " cat" );
for (문자열 이름 : select($(c.getName())).from($(c),cats)
    .where($(c.getKittens()).size().gt( 0 ))
    .fetch()) {
    System.out.println(이름);
}

코드에서 별칭 기능을 사용하려면 다음 두 가져오기를 추가하세요.

import  static com.querydsl.core.alias.Alias.$;
import  static com.querydsl.core.alias.Alias.alias;

다음 예제는 목록 크기에 대한 액세스가 달러 메서드 호출 내에서 발생하는 이전 예제의 변형입니다.

Cat c = alias(Cat.class , " cat" );
for (문자열 이름 : queryFactory.select($(c.getName())).from($(c),cats)
    .where($(c.getKittens().size()).gt( 0 ))
    .fetch()) {
    System.out.println(이름);
}

별칭의 기본이 아닌 유형 및 최종 유형이 아닌 모든 속성은 별칭 자체입니다. 따라서 달러 메소드 범위에서 기본 유형 또는 최종 유형에 도달할 때까지 메소드 호출을 계단식으로 배열할 수 있습니다. 예를 들어

$(c.getMate().getName())

내부적으로는 *c.mate.name*으로 변환되지만

$(c.getMate().getName().toLowerCase())

호출이 추적되지 않으므로 제대로 변환되지 않습니다 toLowerCase().

또한 별칭 유형에 대해서는 getter, size(), contain(Object) 및 get(int)만 호출할 수 있습니다. 다른 모든 호출에서는 예외가 발생합니다.

4. 문제 해결

4.1. 유형 인수가 부족합니다.

Querydsl은 모든 코드 생성 시나리오에서 적절하게 인코딩된 목록 세트, 컬렉션 및 맵 속성이 필요합니다.

부적절하게 인코딩된 필드나 getter를 사용하면 다음 스택 추적이 발생할 수 있습니다.

java.lang.RuntimeException: com.querydsl.jdo.testdomain.Store#products 필드에 대한 예외가 발생했습니다.
  com.querydsl.apt.Processor$2.visitType(Processor.java:117)에서
  com.querydsl.apt.Processor$2.visitType(Processor.java:80)에서
  com.sun.tools.javac.code.Symbol$ClassSymbol.accept(Symbol.java:827)
  com.querydsl.apt.Processor.getClassModel(Processor.java:154)에서
  com.querydsl.apt.Processor.process(Processor.java:191)에서
  ...
원인: java.lang.IllegalArgumentException: 목록에 대한 유형 인수가 부족함
  com.querydsl.apt.APTTypeModel.visitDeclared(APTTypeModel.java:112)에서
  com.querydsl.apt.APTTypeModel.visitDeclared(APTTypeModel.java:40)에서
  com.sun.tools.javac.code.Type$ClassType.accept(Type.java:696)에서
  com.querydsl.apt.APTTypeModel.<init>(APTTypeModel.java:55)에서
  com.querydsl.apt.APTTypeModel.get(APTTypeModel.java:48)에서
  com.querydsl.apt.Processor$2.visitType(Processor.java:114)에서
  ... 35개 더 보기

문제가 있는 필드 선언 및 수정 사항의 예:

    개인 컬렉션 이름; // 잘못된

    개인 컬렉션<String> 이름; // 오른쪽

    개인 지도 직원별 이름; // 잘못된

    개인 맵<String,Employee> EmployeesByName; // 오른쪽

4.2. Querydsl Q 유형의 다중 스레드 초기화

Querydsl Q 유형이 여러 스레드에서 초기화될 때 Q 유형에 순환 종속성이 있으면 교착 상태가 발생할 수 있습니다.

사용하기 쉬운 솔루션은 클래스를 다른 스레드에서 사용하기 전에 단일 스레드에서 초기화하는 것입니다.

com.querydsl.codegen.ClassPathUtils 클래스는 다음과 같이 사용할 수 있습니다.

    ClassPathUtils.scanPackage(Thread.currentThread().getContextClassLoader(), packageToLoad);

packageToLoad를 초기화하려는 클래스의 패키지로 바꿉니다.

 

 

- [출처] Querydsl 참조 가이드

'SpringBoot' 카테고리의 다른 글

Spring data JPA  (0) 2024.01.11