1概要

Querydslは広範なJavaフレームワークであり、SQL

に似たドメイン固有の言語で

型安全なクエリを作成および実行するのに役立ちます。

この記事では、Java Persistence APIを使用したQuerydslについて説明します。

ここでのちょっとした注意はHibernateのためのHQLがQuerydslのための最初のターゲット言語でしたが、最近ではバックエンドとしてJPA、JDO、JDBC、Lucene、Hibernate検索、MongoDB、コレクションとRDFBeanをサポートします。


2準備

まず、必要な依存関係をMavenプロジェクトに追加しましょう。

<properties>
    <querydsl.version>2.5.0</querydsl.version>
</properties>

<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-apt</artifactId>
    <version>${querydsl.version}</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-jpa</artifactId>
    <version>${querydsl.version}</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.6.1</version>
</dependency>

それでは、Maven APTプラグインを設定しましょう。

<project>
    <build>
    <plugins>
    ...
    <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</outputDirectory>
                <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
            </configuration>
        </execution>
        </executions>
    </plugin>
    ...
    </plugins>
    </build>
</project>


JPAAnnotationProcessor

は、

javax.persistence.Entity

アノテーションが付けられたドメインタイプを見つけて、それらのクエリータイプを生成します。


3 Querydsl

によるクエリ

クエリは、ドメインタイプのプロパティを反映して生成されたクエリタイプに基づいて構築されます。また、関数/メソッドの呼び出しは、完全に型保証された方法で構築されています。

クエリのパスと操作はすべての実装で同じです。また、

Query

インタフェースにも共通の基本インタフェースがあります。

** 3.1. エンティティとQuerydslクエリタイプ

**

例を見ながら、最初に使用する単純なエンティティを定義しましょう。

@Entity
public class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String firstname;

    @Column
    private String surname;

    Person() {
    }

    public Person(String firstname, String surname) {
        this.firstname = firstname;
        this.surname = surname;
    }

   //standard getters and setters

}

Querydslは、単純な名前

QPerson

を持つクエリタイプを

Person

と同じパッケージに生成します。

QPerson

は、

Person

タイプの代表として、Querydslクエリで静的に型指定された変数として使用できます。

まず –

QPerson

には静的フィールドとしてアクセスできるデフォルトのインスタンス変数があります。

QPerson person = QPerson.person;

あるいは、このようにあなた自身の

Person

変数を定義することができます。

QPerson person = new QPerson("Erich", "Gamma");


3.2.

JPAQuery


を使用してクエリを作成する

クエリに

JPAQuery

インスタンスを使用できるようになりました。

JPAQuery query = new JPAQuery(entityManager);


entityManager

はJPAの

EntityManager

です。

簡単な例として、名前が ”

Kent

“のすべての人物を取得しましょう。

QPerson person = QPerson.person;
List<Person> persons = query.from(person).where(person.firstName.eq("Kent")).list(person);


from

呼び出しはクエリソースと射影を定義し、

where

部分はフィルタを定義し、

list

は一致したすべての要素を返すようにQuerydslに指示します。

複数のフィルタを使用することもできます。

query.from(person).where(person.firstName.eq("Kent"), person.surname.eq("Beck"));

または

query.from(person).where(person.firstName.eq("Kent").and(person.surname.eq("Beck")));

ネイティブJPQL形式では、クエリは次のようになります。

select person from Person as person where person.firstName = "Kent" and person.surname = "Beck"

「or」を使ってフィルタを組み合わせる場合は、次のパターンを使用します。

query.from(person).where(person.firstName.eq("Kent").or(person.surname.eq("Beck")));

** 4 Querydslにおける順序付けと集約

**

それでは、Querydslライブラリ内で順序付けと集計がどのように機能するかを見てみましょう。


4.1. ご注文

結果を

surname

フィールドの降順に並べることから始めます。

QPerson person = QPerson.person;
List<Person> persons = query.from(person)
    .where(person.firstname.eq(firstname))
    .orderBy(person.surname.desc())
    .list(person);


4.2. 集計

利用可能なものがいくつかあるので(Sum、Avg、Max、Min)、単純な集計を使用しましょう。

QPerson person = QPerson.person;
int maxAge = query.from(person).list(person.age.max()).get(0);

** 4.3.

GroupBy

による集約

**


com.mysema.query.group.GroupBy

クラスは、クエリ結果をメモリに集約するために使用できる集約機能を提供します。

これは、結果として

firstname

をキーとして、

max age

を値として

Map

として返される簡単な例です。

QPerson person = QPerson.person;
Map<String, Integer> results =
  query.from(person).transform(
      GroupBy.groupBy(person.firstname).as(GroupBy.max(person.age)));

** 5 Querydslによるテスト

**

それでは、Querydslを使用してDAO実装を定義しましょう – そして、次の検索操作を定義しましょう:

public List<Person> findPersonsByFirstnameQuerydsl(String firstname) {
    JPAQuery query = new JPAQuery(em);
    QPerson person = QPerson.person;
    return query.from(person).where(person.firstname.eq(firstname)).list(person);
}

それでは、この新しいDAOを使用していくつかのテストを作成し、Querydslを使用して(

PersonDao

クラスに実装された)新しく作成された

Person

オブジェクトを検索し、

GroupBy

クラスを使用した別のテスト集約でテストします。

@Autowired
private PersonDao personDao;

@Test
public void givenExistingPersons__whenFindingPersonByFirstName__thenFound() {
    personDao.save(new Person("Erich", "Gamma"));
    Person person = new Person("Kent", "Beck");
    personDao.save(person);
    personDao.save(new Person("Ralph", "Johnson"));

    Person personFromDb =  personDao.findPersonsByFirstnameQuerydsl("Kent").get(0);
    Assert.assertEquals(person.getId(), personFromDb.getId());
}

@Test
public void givenExistingPersons__whenFindingMaxAgeByName__thenFound() {
    personDao.save(new Person("Kent", "Gamma", 20));
    personDao.save(new Person("Ralph", "Johnson", 35));
    personDao.save(new Person("Kent", "Zivago", 30));

    Map<String, Integer> maxAge = personDao.findMaxAgeByName();
    Assert.assertTrue(maxAge.size() == 2);
    Assert.assertSame(35, maxAge.get("Ralph"));
    Assert.assertSame(30, maxAge.get("Kent"));
}


6. 結論

このチュートリアルでは、Querydslを使ってJPAプロジェクトをビルドする方法を説明しました。

この記事の

完全な実装

はhttps://github.com/eugenp/tutorials/tree/master/persistence-modules/querydsl[githubプロジェクト]にあります – これはEclipseベースのMavenプロジェクトです。そのままインポートして実行するのは簡単です。

ここでの簡単なメモは – 単純なMavenビルド(mvn clean install)を実行して

target/generated-sources

に型を生成し、そしてEclipseを使用している場合はそのフォルダをプロジェクトのソースフォルダとして含めます。